DRF provided a very robus method to query from client. Client can query multiple dataset without adding new endpoint.
For example: Assume we have 2 models, Category
and Article
1 article can be belong to 1 category or no category at all.
Our customer wants to:
- Getting full list of articles
- Filter articles by cateogry ID, category UID
- Order articles by created time
- Order articles by category’s created time
These requirements seem too much but it’s very simple in DRF realm.
All we need are 2 kind of filters:
django_filter
: https://github.com/carltongibson/django-filter (note: use 2.x version)- Build-in
OrderingFilter
of DRF
To use django_filter
, we need 2 steps if we don’t use generics.ListAPIView
:
- Define custom filter
- Tell DRF the filters we want to use
- Declare
filterset_class
in the view we want to use.
Define custom filter:
I recommend to put filters in separate file instead of inside models.py
.
api/apps/article/filters.py
from django_filters import rest_framework as filters
from .models import Article
class ArticleFilter(filters.FilterSet):
category = filters.NumberFilter(field_name='category_id')
category_uid = filters.CharFilter(field_name='category__uid')
class Meta:
model = Article
fields = {
'category': ['exact', 'isnull'],
'category_uid': ['exact'],
}
Tell DRF the filters we want to use in settings.py
:
REST_FRAMEWORK = {
'''
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.OrderingFilter',
...
),
...
}
Declare filter:
class ArticleViewSet(GenericViewSet):
filterset_class = ArticleFilter
ordering_fields = ('id', 'category', )
...
That is, this is the demo: