django-filter Documentation

repository·main·Indexed 26 days ago

https://github.com/carltongibson/django-filter

A reusable Django application that allows users to declaratively add dynamic QuerySet filtering from URL parameters. It provides tools like FilterSet for defining filters via class attributes or Meta classes, FilterView for class-based filtering, and dedicated integration for Django REST Framework.

Tokens
2.1K
Snippets
10
Records
10
Agent score
39%

What's inside django-filter

  1. Create a FilterSet for a Django Model

    main

    To filter a queryset, create a class that inherits from django_filters.FilterSet. You can define filters declaratively by specifying filter types (like CharFilter or NumberFilter) as class attributes, or use the Meta class to automatically generate filters from model fields.

    When defining filters manually, use these key arguments:

    • field_name: The name of the model field to filter on (supports Django's __ relationship syntax).
    • lookup_expr: The Django lookup expression to use (e.g., iexact, gt, icontains).
    import django_filters
    from .models import Product
    
    class ProductFilter(django_filters.FilterSet):
        # Declarative syntax for specific filters
        name = django_filters.CharFilter(lookup_expr='iexact')
    
        class Meta:
            model = Product
            # Automatically generate filters for these fields
            fields = ['price', 'release_date']
  2. Use django-filter with Django REST Framework

    main

    When using Django REST Framework (DRF), import FilterSet from django_filters.rest_framework instead of the standard module. This provides the necessary integration for DRF's filter backends.

    from django_filters import rest_framework as filters
    
    class ProductFilter(filters.FilterSet):
        class Meta:
            model = Product
            fields = ('category', 'in_stock')
  3. Use django-filter for standard Django views

    main

    To create a filtering interface for a Django model, define a class inheriting from django_filters.FilterSet. Use the Meta inner class to specify the model and the fields you want to filter by. In your view, instantiate the filter class with request.GET and a queryset.

    import django_filters
    
    class ProductFilter(django_filters.FilterSet):
        class Meta:
            model = Product
            fields = ['name', 'price', 'manufacturer']
    
    # In your view
    def product_list(request):
        filter = ProductFilter(request.GET, queryset=Product.objects.all())
        return render(request, 'my_app/template.html', {'filter': filter})
  4. Use FilterView for class-based filtering

    main

    Django-filter provides django_filters.views.FilterView, a class-based generic view for handling filtered lists.

    Requirements:

    • Provide either model or filterset_class.
    • If using model, you can optionally provide filterset_fields (a list/tuple of fields) to automatically construct a FilterSet.
    • You must provide a template at <app>/<model>_filter.html.

    Context Variables in Template:

    • filter: The FilterSet instance (contains filter.form).
    • object_list: The resulting filtered queryset.
    # urls.py
    from django.urls import path
    from django_filters.views import FilterView
    from myapp.models import Product
    
    urlpatterns = [
        path("list/", FilterView.as_view(model=Product), name="product-list"),
    ]
  5. Filter the primary queryset using FilterSet.qs

    main

    To restrict the base queryset that the FilterSet operates on (for example, to only show items owned by the current user), override the qs property. You can access the request object via self.request to perform this logic.

    class ArticleFilter(django_filters.FilterSet):
        class Meta:
            model = Article
            fields = [...]
    
        @property
        def qs(self):
            parent = super().qs
            author = getattr(self.request, 'user', None)
            return parent.filter(is_published=True) | parent.filter(author=author)
  6. Use request-based filtering for ModelChoiceFilter

    main

    For ModelChoiceFilter and ModelMultipleChoiceFilter, you can pass a callable to the queryset argument. This callable receives the request object as its only argument, allowing you to dynamically filter the choices available in the filter based on the current user or request context.

    def departments(request):
        if request is None:
            return Department.objects.none()
        company = request.user.company
        return company.department_set.all()
    
    class EmployeeFilter(filters.FilterSet):
        department = filters.ModelChoiceFilter(queryset=departments)
  7. Override default filters using filter_overrides

    main

    You can use filter_overrides in the Meta class to change how all fields of a specific Django model type are handled within the FilterSet. This is useful for applying a consistent filter class or extra configuration (like a custom widget) to all fields of a certain type (e.g., all CharFields).

    class ProductFilter(django_filters.FilterSet):
        class Meta:
            model = Product
            fields = ['name', 'release_date']
            filter_overrides = {
                models.CharField: {
                    'filter_class': django_filters.CharFilter,
                    'extra': lambda f: {
                        'lookup_expr': 'icontains',
                    },
                },
            }
  8. Customize filter behavior with Filter.method

    main

    You can define custom filtering logic by assigning a method name to a filter attribute using the method argument. The specified method must accept (self, queryset, name, value) as arguments and return a filtered queryset.

    class F(django_filters.FilterSet):
        username = CharFilter(method='my_custom_filter')
    
        def my_custom_filter(self, queryset, name, value):
            return queryset.filter(**{
                name: value,
            })
  9. Generate multiple filters using Meta.fields

    main

    The Meta.fields attribute allows you to quickly generate multiple lookup expressions for your model fields.

    • List syntax: fields = ['field1', 'field2'] generates 'exact' lookups for those fields.
    • Dictionary syntax: fields = {'field1': ['lookup1', 'lookup2']} allows you to specify multiple specific lookups for each field.
    • Relationship paths: You can use Django's __ syntax within the fields list to filter on related models (e.g., 'manufacturer__country').
    class ProductFilter(django_filters.FilterSet):
        class Meta:
            model = Product
            fields = {
                'price': ['lt', 'gt'],
                'release_date': ['exact', 'year__gt'],
            }