Movatterモバイル変換


[0]ホーム

URL:


ContentsMenuExpandLight modeDark modeAuto light/dark, in light modeAuto light/dark, in dark modeSkip to content
django-filter 25.1 documentation
django-filter 25.1 documentation

User Guide

Reference Documentation

Developer Documentation

Back to top

Getting Started

Django-filter provides a simple way to filter down a queryset based onparameters a user provides. Say we have aProduct model and we want to letour users filter which products they see on a list page.

Note

If you’re using django-filter with Django Rest Framework, it’s recommendedthat you read theIntegration with DRF docs after this guide.

The model

Let’s start with our model:

fromdjango.dbimportmodelsclassProduct(models.Model):name=models.CharField(max_length=255)price=models.DecimalField(max_digits=5,decimal_places=2)description=models.TextField()release_date=models.DateField()manufacturer=models.ForeignKey(Manufacturer,on_delete=models.CASCADE)

The filter

We have a number of fields and we want to let our users filter based on thename, the price or the release_date. We create aFilterSet for this:

importdjango_filtersclassProductFilter(django_filters.FilterSet):name=django_filters.CharFilter(lookup_expr='iexact')classMeta:model=Productfields=['price','release_date']

As you can see this uses a very similar API to Django’sModelForm. Justlike with aModelForm we can also override filters, or add new ones using adeclarative syntax.

Declaring filters

The declarative syntax provides you with the most flexibility when creatingfilters, however it is fairly verbose. We’ll use the below example to outlinethecore filter arguments on aFilterSet:

classProductFilter(django_filters.FilterSet):price=django_filters.NumberFilter()price__gt=django_filters.NumberFilter(field_name='price',lookup_expr='gt')price__lt=django_filters.NumberFilter(field_name='price',lookup_expr='lt')release_year=django_filters.NumberFilter(field_name='release_date',lookup_expr='year')release_year__gt=django_filters.NumberFilter(field_name='release_date',lookup_expr='year__gt')release_year__lt=django_filters.NumberFilter(field_name='release_date',lookup_expr='year__lt')manufacturer__name=django_filters.CharFilter(lookup_expr='icontains')classMeta:model=Productfields=['price','release_date','manufacturer']

There are two main arguments for filters:

  • field_name: The name of the model field to filter on. You can traverse“relationship paths” using Django’s__ syntax to filter fields on arelated model. ex,manufacturer__name.

  • lookup_expr: Thefield lookup to use when filtering. Django’s__syntax can again be used in order to support lookup transforms.ex,year__gte.

Together, the fieldfield_name andlookup_expr represent a complete Djangolookup expression. A detailed explanation of lookup expressions is provided inDjango’slookup reference. django-filter supports expressions containingboth transforms and a final lookup.

Generating filters with Meta.fields

The FilterSet Meta class provides afields attribute that can be used foreasily specifying multiple filters without significant code duplication. Thebase syntax supports a list of multiple field names:

importdjango_filtersclassProductFilter(django_filters.FilterSet):classMeta:model=Productfields=['price','release_date']

The above generates ‘exact’ lookups for both the ‘price’ and ‘release_date’fields.

Additionally, a dictionary can be used to specify multiple lookup expressionsfor each field:

importdjango_filtersclassProductFilter(django_filters.FilterSet):classMeta:model=Productfields={'price':['lt','gt'],'release_date':['exact','year__gt'],}

The above would generate ‘price__lt’, ‘price__gt’, ‘release_date’, and‘release_date__year__gt’ filters.

Note

The filter lookup type ‘exact’ is an implicit default and therefore neveradded to a filter name. In the above example, the release date’s exactfilter is ‘release_date’, not ‘release_date__exact’. This can be overriddenby the FILTERS_DEFAULT_LOOKUP_EXPR setting.

Items in thefields sequence in theMeta class may include“relationship paths” using Django’s__ syntax to filter on fields on arelated model:

classProductFilter(django_filters.FilterSet):classMeta:model=Productfields=['manufacturer__country']

Overriding default filters

Likedjango.contrib.admin.ModelAdmin, it is possible to overridedefault filters for all the models fields of the same kind usingfilter_overrides on theMeta class:

classProductFilter(django_filters.FilterSet):classMeta:model=Productfields={'name':['exact'],'release_date':['isnull'],}filter_overrides={models.CharField:{'filter_class':django_filters.CharFilter,'extra':lambdaf:{'lookup_expr':'icontains',},},models.BooleanField:{'filter_class':django_filters.BooleanFilter,'extra':lambdaf:{'widget':forms.CheckboxInput,},},}

Request-based filtering

TheFilterSet may be initialized with an optionalrequest argument. Ifa request object is passed, then you may access the request during filtering.This allows you to filter by properties on the request, such as the currentlylogged-in user or theAccepts-Languages header.

Note

It is not guaranteed that arequest will be provided to theFilterSetinstance. Any code depending on a request should handle theNone case.

Filtering the primary.qs

To filter the primary queryset by therequest object, simply override theFilterSet.qs property. For example, you could filter blog articles to onlythose that are published and those that are owned by the logged-in user(presumably the author’s draft articles).

classArticleFilter(django_filters.FilterSet):classMeta:model=Articlefields=[...]@propertydefqs(self):parent=super().qsauthor=getattr(self.request,'user',None)returnparent.filter(is_published=True) \|parent.filter(author=author)

Filtering the related queryset forModelChoiceFilter

Thequeryset argument forModelChoiceFilter andModelMultipleChoiceFiltersupports callable behavior. If a callable is passed, it will be invoked with therequest as its only argument. This allows you to perform the same kinds ofrequest-based filtering without resorting to overridingFilterSet.__init__.

defdepartments(request):ifrequestisNone:returnDepartment.objects.none()company=request.user.companyreturncompany.department_set.all()classEmployeeFilter(filters.FilterSet):department=filters.ModelChoiceFilter(queryset=departments)...

Customize filtering withFilter.method

You can control the behavior of a filter by specifying amethod to performfiltering. View more information in themethod reference.Note that you may access the filterset’s properties, such as therequest.

classF(django_filters.FilterSet):username=CharFilter(method='my_custom_filter')classMeta:model=Userfields=['username']defmy_custom_filter(self,queryset,name,value):returnqueryset.filter(**{name:value,})

The view

Now we need to write a view:

defproduct_list(request):f=ProductFilter(request.GET,queryset=Product.objects.all())returnrender(request,'my_app/template.html',{'filter':f})

If a queryset argument isn’t provided then all the items in the default managerof the model will be used.

If you want to access the filtered objects in your views, for example if youwant to paginate them, you can do that. They are in f.qs

The URL conf

We need a URL pattern to call the view:

path('list/',views.product_list,name="product-list")

The template

And lastly we need a template:

{% extends "base.html" %}{% block content %}    <form method="get">        {{ filter.form.as_p }}        <input type="submit" />    </form>    {% for obj in filter.qs %}        {{ obj.name }} - ${{ obj.price }}<br />    {% endfor %}{% endblock %}

And that’s all there is to it! Theform attribute contains a normalDjango form, and when we iterate over theFilterSet.qs we get the objects inthe resulting queryset.

Generic view & configuration

In addition to the above usage there is also a class-based generic viewincluded in django-filter, which lives atdjango_filters.views.FilterView.You must provide either amodel orfilterset_class argument, similar toListView in Django itself:

# urls.pyfromdjango.urlsimportpathfromdjango_filters.viewsimportFilterViewfrommyapp.modelsimportProducturlpatterns=[path("list/",FilterView.as_view(model=Product),name="product-list"),]

If you provide amodel optionally you can setfilterset_fields to specify a list or a tuple ofthe fields that you want to include for the automatic construction of the filterset class.

You must provide a template at<app>/<model>_filter.html which gets thecontext parameterfilter. Additionally, the context will containobject_list which holds the filtered queryset.

A legacy functional generic view is still included in django-filter, althoughits use is deprecated. It can be found atdjango_filters.views.object_filter. You must provide the same argumentsto it as the class based view:

# urls.pyfromdjango.urlsimportpathfromdjango_filters.viewsimportobject_filterfrommyapp.modelsimportProducturlpatterns=[path("list/",object_filter,{'model':Product},name="product-list"),]

The needed template and its context variables will also be the same as theclass-based view above.

On this page

[8]ページ先頭

©2009-2025 Movatter.jp