Reputation: 93
I have an order model:
class Order(models.Model):
profile = models.ForeignKey(Profile, null=True, blank=True)
Which returns all possible profiles for an order, which is not necessary and slowing down the loading of the admin order page.
I want the profile returned to simply be the profile of the user who placed the order. I've tried changing it to:
class Order(models.Model):
profile = models.ForeignKey(Profile, null=True, blank=True, limit_choices_to={'order': 99999})
which returns the correct profile for order number 99999, but how can I get this dynamically. The Order model is not aware of the 'self', but the order number is contained in the URL.
What is the best way to do this?
Upvotes: 0
Views: 419
Reputation: 296
I assume from the context you're referring to the display on the Django Admin page. If you set raw_id_fields = {'my_foreign_key'}
you will get a number, text description of related model (from str) and a nice popup box to open an instance of the admin page for your related models.
You could alternatively use list_select_related = True to get the same behaivour you have now but with a couple of order of magnitudes lower number of queries.
Upvotes: 0
Reputation: 93
I took another look at this and it seems to be working, although it seems like a bit of hack! The problem was that the order number doesn't seem to exist in the request so I am parsing the URL requested. I put this in my order admin:
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "profile":
try:
order = int(filter(str.isdigit, str(request.path_info)))
except:
order = request.GET.get('order')
kwargs["queryset"] = Profile.objects.filter(order=order)
return super(OrderAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
The line that filters the url string for an integer works for the change order page of the admin, but didn't work for the order page overview, so I added the try/except. Any suggestions/improvements welcome!
Upvotes: 0
Reputation: 178
If you are using the Django Admin, you can override the method formfield_for_foreignkey
on your ModelAdmin
class to modify the queryset for the profile field dinamically based on a GET parameter for instance (as you have access to request
inside the method.
Look at this example from the docs (adapted for your case):
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "profile":
# You can get the order number from the GET parameter:
# order = request.GET.get('order')
# or a fixed number:
order = '12345'
kwargs["queryset"] = Profile.objects.filter(order=order)
return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Reference in the docs: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_foreignkey
Upvotes: 0