Usage¶
Vanilla¶
In its simplest form, Django URL Filter usage resolves around FilterSet
.
They can be used manually:
from django import forms
from url_filter.filter import Filter
from url_filter.filtersets import FilterSet
class ProfileFilterSet(FilterSet):
lives_in_country = Filter(form_field=forms.CharField())
class UserFilterSet(FilterSet):
username = Filter(form_field=forms.CharField(), lookups=['exact'])
email = Filter(form_field=forms.CharField())
joined = Filter(form_field=forms.DateField())
profile = ProfileFilterSet()
query = QueryDict(
'email__contains=gmail'
'&joined__year=2015'
'&profile__lives_in_country__iexact=us'
)
fs = UserFilterSet(data=query, queryset=User.objects.all())
filtered_users = fs.filter()
Notable things to mention from above:
FilterSet
can be used as aFilter
within anotherFilterSet
hence allowing filtering by related models.form_field
is used to validate the filter value. Each lookup however can overwrite validation. For exampleyear
lookup will useIntegerField
rather thenDateField
.Filter
can restrict allowed lookups for that field by usinglookup
parameter
Django¶
Instead of manually creating FilterSet
, Django URL Filter comes with
ModelFilterSet
which greatly simplifies the task:
from django import forms
from url_filter.filtersets import ModelFilterSet
class UserFilterSet(ModelFilterSet):
class Meta(object):
model = User
fields = ['username', 'email', 'joined', 'profile']
Notable things:
fields
can actually be completely omitted. In that caseFilterSet
will use all fields available in the model, including related fields.filters can be manually overwritten when custom behavior is required:
class UserFilterSet(ModelFilterSet): username = Filter(form_field=forms.CharField(max_length=15)) class Meta(object): model = User fields = ['username', 'email', 'joined', 'profile']
SQLAlchemy¶
SQLAlchemy works very similar to how Django backend works. For example:
from django import forms
from url_filter.backend.sqlalchemy import SQLAlchemyFilterBackend
from url_filter.filtersets.sqlalchemy import SQLAlchemyModelFilterSet
class UserFilterSet(SQLAlchemyModelFilterSet):
filter_backend_class = SQLAlchemyFilterBackend
class Meta(object):
model = User # this model should be SQLAlchemy model
fields = ['username', 'email', 'joined', 'profile']
fs = UserFilterSet(data=QueryDict(), queryset=session.query(User))
fs.filter()
Notable things:
- this works exactly same as
ModelFitlerSet
so refer above for some of general options. filter_backend_class
must be provided since otherwiseDjangoFilterBackend
will be used which will obviously not work with SQLAlchemy models.queryset
given to the queryset should be SQLAlchemy query object.
Integrations¶
Django URL Filters tries to be usage-agnostic and does not assume
how FilterSet
is being used in the application. It does however
ship with some common integrations to simplify common workflows.
Django REST Framework¶
Django URL Filter can rather easily be integrated with DRF. For that, a DRF filter backend is implemented and can be used in settings:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'url_filter.integrations.drf.DjangoFilterBackend',
]
}
or manually set in the viewset:
class MyViewSet(ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
filter_backends = [DjangoFilterBackend]
filter_fields = ['field1', 'field2']
Note in the example above, fields to be filtered on are explicitly
specified in the filter_fields
attribute. Alternatively if more
control over FilterSet
is required, it can be set explicitly:
class MyFilterSet(FilterSet):
pass
class MyViewSet(ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
filter_backends = [DjangoFilterBackend]
filter_class = MyFilterSet
Backends¶
FilterSet
by itself is decoupled from the actual filtering
of the queryset. Backend can be swapped by using filter_backend_class
:
class FooFilterSet(FilterSet):
filter_backend_class = MyFilterBackend
Note
Currently only DjangoFilterBackend
is implemented which uses
Django ORM however more backends are planned for.