FilterSet Guide¶
This document provides a guide on using additional FilterSet features.
Meta options¶
Ordering using order_by
¶
You can allow the user to control ordering by providing the
order_by
argument in the Filter’s Meta class. order_by
can be either a
list
or tuple
of field names, in which case those are the options, or
it can be a bool
which, if True, indicates that all fields that
the user can filter on can also be sorted on. An example of ordering using a list:
import django_filters
class ProductFilter(django_filters.FilterSet):
price = django_filters.NumberFilter(lookup_expr='lt')
class Meta:
model = Product
fields = ['price', 'release_date']
order_by = ['price']
If you want to control the display of items in order_by
, you can set it to
a list or tuple of 2-tuples in the format (field_name, display_name)
.
This lets you override the displayed names for your ordering fields:
order_by = (
('name', 'Company Name'),
('average_rating', 'Stars'),
)
Note that the default query parameter name used for ordering is o
. You
can override this by setting an order_by_field
attribute on the
FilterSet
class to the string value you would like to use.
Custom Forms using form
¶
The inner Meta
class also takes an optional form
argument. This is a
form class from which FilterSet.form
will subclass. This works similar to
the form
option on a ModelAdmin.
Group fields with together
¶
The inner Meta
class also takes an optional together
argument. This
is a list of lists, each containing field names. For convenience can be a
single list/tuple when dealing with a single set of fields. Fields within a
field set must either be all or none present in the request for
FilterSet.form
to be valid:
import django_filters
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
fields = ['price', 'release_date', 'rating']
together = ['rating', 'price']
Non-Meta options¶
Note that these options do not go in the Meta class, they are specified directly in your FilterSet class.
- filter_overrides
- order_by_field
- strict
strict
¶
The strict
option controls whether results are returned when an invalid
value is specified by the user for any filter field. By default, strict
is
set to STRICTNESS.RETURN_NO_RESULTS
meaning that an empty queryset is
returned if any field contains an invalid value. You can loosen this behavior
by setting strict
to STRICTNESS.IGNORE
which will effectively ignore a
filter field if its value is invalid. A third option of
STRICTNESS.RAISE_VALIDATION_ERROR
will cause a ValidationError
to be
raised if any field contains an invalid value.
Overriding FilterSet
methods¶
filter_for_lookup()
¶
Prior to version 0.13.0, filter generation did not take into account the
lookup_expr
used. This commonly caused malformed filters to be generated
for ‘isnull’, ‘in’, and ‘range’ lookups (as well as transformed lookups). The
current implementation provides the following behavior:
- ‘isnull’ lookups return a
BooleanFilter
- ‘in’ lookups return a filter derived from the CSV-based
BaseInFilter
. - ‘range’ lookups return a filter derived from the CSV-based
BaseRangeFilter
.
If you want to override the filter_class
and params
used to instantiate
filters for a model field, you can override filter_for_lookup()
. Ex:
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
fields = {
'release_date': ['exact', 'range'],
}
@classmethod
def filter_for_lookup(cls, f, lookup_type):
# override date range lookups
if isinstance(f, models.DateField) and lookup_type == 'range':
return django_filters.DateRangeFiler, {}
# use default behavior otherwise
return super(ProductFilter, cls).filter_for_lookup(f, lookup_type)
get_ordering_field()
¶
If you want to use a custom widget, or in any other way override the ordering
field you can override the get_ordering_field()
method on a FilterSet
.
This method just needs to return a Form Field.
Ordering on multiple fields, or other complex orderings can be achieved by
overriding the FilterSet.get_order_by()
method. This is passed the selected
order_by
value, and is expected to return an iterable of values to pass to
QuerySet.order_by
. For example, to sort a User
table by last name, then
first name:
class UserFilter(django_filters.FilterSet):
class Meta:
order_by = (
('username', 'Username'),
('last_name', 'Last Name')
)
def get_order_by(self, order_value):
if order_value == 'last_name':
return ['last_name', 'first_name']
return super(UserFilter, self).get_order_by(order_value)