Filter DjangoFilterBackend:
DRF generic list view returns by default the entire queryset
query result, but usually only required part of the business, in which case you need to use the "filters" to limit the returned result set.
The most stupid way is to inherit GenericAPIView
class or inherited GenericAPIView
class and override the .get_queryset()
method, we first look at the Class View to add a methodget_queryset
from rest_framework import generics
class ArticleViewSet(generics.ListAPIView):
queryset = Article.objects.all() # 查询结果集
serializer_class = ArticleSerializer # 序列化类
pagination_class = ArticlePagination # 自定义分页会覆盖settings全局配置的
def get_queryset(self):
queryset = Article.objects.all()
read_num = self.request.query_params.get('read_num', 0) # 获取查询字段值
if read_num:
queryset = queryset.filter(read_num__gt=int(read_num))
return queryset
Test results
- When the transfer
read_num=83
method according toget_queryset
the determination condition is greater than the find83
are3
records.
- We try again if you do not pass, recorded seven records found.
summary
We rewrite the above get_queryset
method to achieve the filtering effect, if to do so in a complex filter conditions, the code would be too redundant, and it is possible to achieve most of the code have been repeating similar function in their daily operations, we need to Gets the specified condition data, for example, the article, we need to specify the classification, Views, and other Chan-point number. Sometimes we need to be sorted in accordance with Views. These require us to do more to expand ArticleViewSet.
django-filter module
django-filter
Library includes a DjangoFilterBackend
class that supports REST
highly customizable framework in the field of filtration.
First installationdjango-filter
pip install django-filter
Then django_filters
add to Django
the INSTALLED_APPS
.
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
Or applied to a single filter or ViewSet View (for general use such ):
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
class ArticleViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
queryset = Article.objects.all() # 查询结果集
serializer_class = ArticleSerializer # 序列化类
pagination_class = ArticlePagination # 自定义分页会覆盖settings全局配置的
# 过滤器
filter_backends = (DjangoFilterBackend,)
# 如果要允许对某些字段进行过滤,可以使用filter_fields属性。
filter_fields = ('title', 'category')
# def get_queryset(self):
# queryset = Article.objects.all()
# read_num = self.request.query_params.get('read_num', 0)
#
# if read_num:
# queryset = queryset.filter(read_num__gt=int(read_num))
#
# return queryset
Test results
As can be seen by adding the corresponding add filter and the filter related fields, note that this is an exact match between fields and a relationship, if a is empty, in other matches, such as
title=测试&category=
is according
title
to pinpoint.
Custom filter class
According to the default matching precision, if you want to achieve a fuzzy search can be custom filter class, then filtered filter_class designated collections.
New filter filefilters.py
from django_filters import rest_framework
from article.models import Article
class AriticleFilter(rest_framework.FilterSet):
min_read = rest_framework.NumberFilter(field_name='read_num', lookup_expr='gte')
max_read = rest_framework.NumberFilter(field_name='read_num', lookup_expr='lte')
title = rest_framework.CharFilter(field_name='title', lookup_expr='icontains')
class Meta:
model = Article
fields = ['title', 'category', 'min_read', 'max_read']
Modify the view class
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from .filters import AriticleFilter
class ArticleViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
queryset = Article.objects.all() # 查询结果集
serializer_class = ArticleSerializer # 序列化类
pagination_class = ArticlePagination # 自定义分页会覆盖settings全局配置的
# 过滤器
filter_backends = (DjangoFilterBackend,)
# 如果要允许对某些字段进行过滤,可以使用filter_fields属性。
#filter_fields = ('title', 'category')
# 使用自定义过滤器
filter_class = AriticleFilter
# def get_queryset(self):
# queryset = Article.objects.all()
# read_num = self.request.query_params.get('read_num', 0)
#
# if read_num:
# queryset = queryset.filter(read_num__gt=int(read_num))
#
# return queryset
Test results:
Search SearchFilter
If you want to explicitly specify which fields can be searched, you can use search_fields property defaults can serializer_class
be read in any search field on the properties of the specified serializer:
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
from .filters import AriticleFilter
class ArticleViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
queryset = Article.objects.all() # 查询结果集
serializer_class = ArticleSerializer # 序列化类
pagination_class = ArticlePagination # 自定义分页会覆盖settings全局配置的
# 过滤器
filter_backends = (DjangoFilterBackend,filters.SearchFilter,)
# 如果要允许对某些字段进行过滤,可以使用filter_fields属性。
#filter_fields = ('title', 'category')
# 使用自定义过滤器
filter_class = AriticleFilter
search_fields = ('title', 'description', 'content')
As it can be seen more than a search box
By default, the search will use the case-insensitive partial match. Search parameters can contain multiple search terms, they should be spaces and / or commas. If you use multiple search terms, only when all the terms provided matches, will return to the object in the list. By default, the search parameter is named "search", but this may be overwritten SEARCH_PARAM set.
The search behavior may be restricted by prepending various characters to the search_fields.
You can limit your search behavior by adding some characters in search_fields as follows:
'^': to start the search string xx
'=': exact match
'@': full text Search (currently only supports MySQL backend Django's)
'$': regular expression search
as: search_fields = ( '@username', '= email')
Sequence
OrderingFilter class field support for a single query result set to be sorted.
By default, the query parameter is named "ordering", but this may be overwritten ORDERING_PARAM set.
You can use ordering_fields property explicitly specify which fields can perform sort, which helps prevent accidental data leakage, such as allowing users to password hash fields or other sensitive data is sorted.
If no ordering_fields the property is filtered on any readable field can serializer_class serializer attribute specified.
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
from .filters import AriticleFilter
class ArticleViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
queryset = Article.objects.all() # 查询结果集
serializer_class = ArticleSerializer # 序列化类
pagination_class = ArticlePagination # 自定义分页会覆盖settings全局配置的
# 过滤器 过滤,搜索,排序
filter_backends = (DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter)
# 如果要允许对某些字段进行过滤,可以使用filter_fields属性。
#filter_fields = ('title', 'category')
# 使用自定义过滤器
filter_class = AriticleFilter
# 搜索
search_fields = ('title', 'description', 'content')
# 排序
ordering_fields = ('id', 'read_num')
effect:
Reproduced in: https: //www.jianshu.com/p/292a06275712