I need a way to modify one ModelAdmin member variable from another ModelAdmin. So I though maybe I could use a global variable. However, if there where multiple users using the app at the same time, then the global variable would keep on getting changed unexpectedly and all hell would break loose.
Is there any method in Django would allow me to modify one ModelAdmin member variable from another ModelAdmin?
Or am I making a design mistake? Am I making this harder than it really is or am I missing something? What about using threading and locks? Message passing??? Events?!?!?! HELP
Here’s the whole story. My app lets it’s users build a PC by choosing compatible CPU, motherboard, memory, and hard drives (in that order). By choosing a cpu, they’re limited to motherboards with the CPU’s socket. By choosing a motherboard with DDR3 dimms, they’re limited to DDR3 memory, and so on.
Also, sense there can be many of the same parts per system (example: memory modules, but they must be identical), I had to create ManyToManyField relationships and specify the intermediary table (with an extra count field) with the through arg. This requires that InlineAdmin models be used to display the fields in the admin page.
To my delight, the raw_id_field variable caused the dropdown widget to be replaced with a button that pops up a form identical to change_list.html and allows users to filter/sort/search for the part they want. However, this was not good enough for my boss. Now I need those filters to be predefined according to earlier selections (i.e. filter for Memory with DDR3 after selecting a motherboard with DDR3). So I implimented this: Default filter in Django admin but I need a way to set the CpuAdmin.default_filters from the PcAdmin dynamically based on what other choices they made.
My models, only including one part model for brevity:
# models.py
class CPU(Part):
partNum = models.CharField(max_length=60)
price = models.DecimalField(precision=2)
socket = models.CharField(max_length=60)
numCores = models.CharField(max_length=60)
class PC(models.Model):
name = models.CharField(max_length=60)
customer = models.CharField(max_length=60)
cpuChoices = models.ManyToManyField(CPU, through='PcCpuChoice')
memoryChoices = models.ManyToManyField(Memory, through='PcMemoryChoice')
hardDriveChoices = models.ManyToManyField(HardDrive, through='PcHardDriveChoice')
motherBoardChoices = models.ManyToManyField(MotherBoard, through='PcMotherboardChoice')
class PcCpuChoice(models.Model):
pc = models.ForeignKey(PC, unique=False)
cpu = models.ForeignKey(CPU, unique=False)
count = models.IntegerField()
# admin.py
class PartAdmin(admin.ModelAdmin):
class Meta:
abstract = True
search_fields = ['partNum', 'description', 'model']
default_filter = []
def changelist_view(self, request, extra_context=None):
if not request.GET.has_key(self.default_filter[0]):
q = request.GET.copy()
q[self.default_filter[0]] = self.default_filter[1]
request.GET = q
request.META['QUERY_STRING'] = request.GET.urlencode()
return super(PartAdmin,self).changelist_view(request, extra_context=extra_context)
class CpuAdmin(PartAdmin):
list_filter = ['brand', 'socket', 'numCores', 'graphics']
list_display = ('partNum', 'description', 'brand', 'model', 'markupPrice', 'clockSpeed', 'watts', 'voltage')
default_filter = ['numCores','8'] # need to change this from PcAdmin!!!
class PcCpuInline(admin.TabularInline):
model = PcCpuChoice
extra = 1
max_num = 1
raw_id_fields = ['cpu']
class PcAdmin(admin.ModelAdmin):
inlines = [PcCpuInline, PcMotherboardInline, PcMemoryInline, PcHardDriveInline]
admin.site.register(PC, PcAdmin)
Thank you @PeterRowell for pointing me in the right direction. I used django sessions to store the filters, javascript to send a request to the server to update the filters when they load the form and to delete them when they leave the form, some view functions to handle those request, added a function to the model (with the request as a parameter) to update the filters per what parts where already saved, and override the
changelist_viewfunction of the PartAdmin to use the filters in request.session to modify the query string. That was a lot of code in a lot of different files, but here are some of the highlights that will hopefully help someone looking for a solution like this:All the models posted in the question stayed pretty much the same.
The views for the PC:
Here is the javascript that was placed in the change_form.html (added it via the extra_context param in PcAdmin add_view and change_view functions)
And finally, the function that was added to PartAdmin:
Oh, and the changelist_view function of PartAdmin did change a little: