Given the following models
class AnotherModel(models.Model): n = models.IntegerField() class MyModel(models.Model): somefield = models.ForeignKey(AnotherModel)
and admin
class MyModelAdmin(admin.ModelAdmin): list_filter = ('somefield',)
how can I filter the instances of AnotherModel
to show only those with a given n
value in my admin filter?
I need something like:
Filter
By somefield
all
[list of AnotherModel instances with given n]
To override default queryset in Python Django admin, we can override the get_queryset method in our model. to add the get_queryset into MyModelAdmin . In it, we call call the super constructor with MyModelAdmin and self . And we get the queryset wirth get_queryset from the super class.
The filter() method is used to filter you search, and allows you to return only the rows that matches the search term.
See ModelAdmin.queryset and ModelAdmin.formfield_for_foreignkey. From the docs:
The queryset method on a ModelAdmin returns a QuerySet of all model instances that can be edited by the admin site. One use case for overriding this method is to show objects owned by the logged-in user:
class MyModelAdmin(admin.ModelAdmin): def queryset(self, request): qs = super(MyModelAdmin, self).queryset(request) if request.user.is_superuser: return qs return qs.filter(author=request.user)
The formfield_for_foreignkey method on a ModelAdmin allows you to override the default formfield for a foreign keys field. For example, to return a subset of objects for this foreign key field based on the user:
class MyModelAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "car": kwargs["queryset"] = Car.objects.filter(owner=request.user) return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
This uses the HttpRequest instance to filter the Car foreign key field to only display the cars owned by the User instance.
[update]
Sorry, I failed to read the "filter" part. In Django >= 1.4 you can pass a subclass of django.contrib.admin.SimpleListFilter
in the list_filter argument list, which you can use in order to override the lookups and queryset methods.
from datetime import date from django.contrib import admin from django.utils.translation import ugettext_lazy as _ class DecadeBornListFilter(admin.SimpleListFilter): # Human-readable title which will be displayed in the # right admin sidebar just above the filter options. title = _('decade born') # Parameter for the filter that will be used in the URL query. parameter_name = 'decade' def lookups(self, request, model_admin): """ Returns a list of tuples. The first element in each tuple is the coded value for the option that will appear in the URL query. The second element is the human-readable name for the option that will appear in the right sidebar. """ return ( ('80s', _('in the eighties')), ('90s', _('in the nineties')), ) def queryset(self, request, queryset): """ Returns the filtered queryset based on the value provided in the query string and retrievable via `self.value()`. """ # Compare the requested value (either '80s' or '90s') # to decide how to filter the queryset. if self.value() == '80s': return queryset.filter(birthday__gte=date(1980, 1, 1), birthday__lte=date(1989, 12, 31)) if self.value() == '90s': return queryset.filter(birthday__gte=date(1990, 1, 1), birthday__lte=date(1999, 12, 31)) class PersonAdmin(admin.ModelAdmin): list_filter = (DecadeBornListFilter,)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With