Integration with Django-filter¶
django-rest-framework-datatables will always use
iregex queries on all columns, which may be costly. More
fine-grained control on the generated database queries can be achieved
Integration with Django-filter is provided through
DatatablesFilterBackend classes. These may be found in the
Using the new
DatatablesFilterBackend simply requires changing the
import path. Instead of importing from
import from the
from django_filters import filters from rest_framework_datatables.django_filters.backends import DatatablesFilterBackend from rest_framework_datatables.django_filters.filterset import DatatablesFilterSet from rest_framework_datatables.django_filters.filters import GlobalFilter class GlobalCharFilter(GlobalFilter, filters.CharFilter): pass class AlbumGlobalFilter(GlobalFilter): """Filter name, artist and genre by name with icontains""" name = GlobalCharFilter(lookup_expr='icontains') genres = GlobalCharFilter(field_name='genres__name', lookup_expr='icontains') artist = GlobalCharFilter(field_name='artist__name', lookup_expr='icontains') year = GlobalCharFilter() class Meta: model = Album fields = '__all__' class AlbumGlobalViewSet(viewsets.ModelViewSet): queryset = Album.objects.all() serializer_class = AlbumSerializer filter_backends = (DatatablesFilterBackend,) filterset_class = AlbumGlobalFilter
Differences and Limitations¶
data-data attribute or the
parameter for the column must contain the name of the filter attribute
on the filterset.
DjangoFilterBackend uses the same parser for the
queries generated by
data-name attribute (or
columns[<n>][name] query parameter) is completely ignored by the
You can specify the lookup in the
lookup_expr kwarg on the
Filter. The ordering is implemented by looking at the
lookup_expr attributes of the filters.
(Because of that, the
keep parameter will not have the same
semantics. It will cause the renderer to return the column, but it
won’t be respected for global search by the backend and filterset.
That means that only columns defined in the datatable can be
The Django-Rest-Framework browsable api will not support global
filters and the
advantage of the automatic widgets generated by
The above example will act as a drop-in replacement for the standard
django-rest-framework-datatables, which uses
iregex for local and global queries.
With large tables this might generate very inefficient queries especially for non-string datatatypes.
By simply not using the
GlobalFilter mixin, you can switch off
global search per column to gain efficiency.
class AlbumGlobalFilter(AlbumFilter): """Filter name, artist and genre by name with icontains""" name = GlobalCharFilter(lookup_expr='icontains') genres = GlobalCharFilter(field_name='genres__name', lookup_expr='icontains') artist = GlobalCharFilter(field_name='artist__name', lookup_expr='icontains') class Meta: model = Album fields = '__all__'
This will revert the
year field to the
automatically generated by
Django-filter which will require an
exact number match.
Also you can use the capability of
Django-filter to automatically
generate the FilterSet for you:
class AlbumFilterViewSet(viewsets.ModelViewSet): queryset = Album.objects.all() serializer_class = AlbumSerializer filter_backends = [DatatablesFilterBackend] filterset_fields = '__all__'
In this case there will be no support for regular expressions,
icontains or global searches, as
Django-filter will use
automatic lookups (e.g
exact for strings), and you’ll need to add
appropriate widgets to the datatable, because
genres will need a
yadcf to ease that task.
See the example app for an example of multiple
Customizing (global) queries¶
The defined filters will be used to filter the column search queries.
Global queries are implemented with the optional
GlobalFilter mixin. This will generate
iregex lookups by default.
If you want more fine-grained control over queries, you can simply define your own filters.
Only filters that provide a
global_q method will support global
global_q method (as for example in the
mixin), should return a Q-object
for the global field query. All these Q-objects will be combined with
| (OR) and the resulting Q-object will be used used to filter the
queryset that was returned by the applying the column filters.
This logic is identical to the one implemented by plain