Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override the queryset giving the filters in list_filter?

Tags:

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]

like image 270
jul Avatar asked Sep 21 '12 00:09

jul


People also ask

How do I override Queryset?

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.

What is the purpose of filter () method in Django?

The filter() method is used to filter you search, and allows you to return only the rows that matches the search term.


1 Answers

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,) 
like image 113
Paulo Scardine Avatar answered Oct 02 '22 05:10

Paulo Scardine