一、普通过滤
(一)get_queryset
get_queryset方法是GenericAPIView提供的一个方法,旨在返回queryset数据集,而过滤就是要在这个方法返回数据集之前对数据进行筛选,然后返回筛选后的数据即可,那么也就是要求需要重写这个方法:
def get_queryset(self): """ Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using `self.queryset`. This method should always be used rather than accessing `self.queryset` directly, as `self.queryset` gets evaluated only once, and those results are cached for all subsequent requests. You may want to override this if you need to provide different querysets depending on the incoming request. (Eg. return a list of items that is specific to the user) """ assert self.queryset is not None, ( "'%s' should either include a `queryset` attribute, " "or override the `get_queryset()` method." % self.__class__.__name__ ) queryset = self.queryset if isinstance(queryset, QuerySet): # Ensure queryset is re-evaluated on each request. queryset = queryset.all() return queryset
源码中的这个方法会从视图配置中获得queryset,然后判断是否属于QuerySet类型,如果属于,就会返回这个queryset。
(二)实例
- 请求API
class BookView(GenericViewSet): serializer_class = BookModelSerializer def get_queryset(self): queryset = models.Book.objects.all() title = self.request.query_params.get('title',None) if title is not None: queryset = models.Book.objects.filter(title=title).all() return queryset def list(self,request,*args,**kwargs): queryset= self.get_queryset() bs=self.get_serializer(queryset,many=True) return Response(bs.data)
- 路由配置:
注意如果需要过滤,url中需要加入base_name属性,并且base_name的值就是过滤参数的名称:
router=routers.DefaultRouter() router.register('books',views.BookView,base_name="title")
- 生成的路由:
^books/$ [name='title-list'] ^books\.(?P<format>[a-z0-9]+)/?$ [name='title-list']
- 请求地址:
http://127.0.0.1:8020/books/?title=语文
二、django-filter过滤
(一)django-filter的简单使用
1、安装django-filter
pip install django-filter
2、注册django-filter
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', 'rest_framework', 'django_filters', #注册django-filter ]
3、设置通用过滤后端
- 全局配置
REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) }
- 局部视图设置
import django_filters.rest_framework class BookView(GenericViewSet): queryset = models.Book.objects.all() serializer_class = BookModelSerializer filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
4、指定筛选字段
如果需求都是些简单类型的筛选,那么可以在view或viewSet里面设置一个filter_fields属性,列出所有依靠筛选的字段集合。
import django_filters.rest_framework from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet): ... filter_fields = ('title',) #列出搜索字段 ...
5、进行访问
- 路由配置
from rest_framework import routers
router=routers.DefaultRouter()
router.register('books',views.BookView) #无需base_name参数
urlpatterns = [ re_path('',include(router.urls)), ]
- 生成的路由
^books/$ [name='book-list'] ^books\.(?P<format>[a-z0-9]+)/?$ [name='book-list'] ^books/(?P<pk>[^/.]+)/$ [name='book-detail'] ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='book-detail']
- 进行访问
http://127.0.0.1:8020/books/?title=语文
(二)FilterSet的简单使用
上面所搜索的字段是一对一的关系,没有涉及到外键以及多对多字段,如果有外键或者多对多关系,可以在filter_fields中使用‘__’进行跨越:
class BookView(ModelViewSet): queryset = models.Book.objects.all() serializer_class = BookModelSerializer filter_backends = (django_filters.rest_framework.DjangoFilterBackend,) # 列出搜索字段,其中publish__name为ForeignKey字段,authors__name为ManyToMany字段 filter_fields = ('title','publish__name','authors__name')
class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField(null=True,blank=True) publish=models.ForeignKey("Publish",on_delete=models.CASCADE) authors=models.ManyToManyField("Author") def __str__(self): return self.title