作者 | 大江狗  责编 | 张文

来源 | Python Web 与 Django 开发

(ID:Python_Web_Django)

在本篇文章中我们将向你演示如何在 Django REST Framework 中对分页结果进行进一步过滤和排序。

前面教程中当你发送 GET 请求到 /v1/articles?page=2 时,可以得到下面返回的分页数据列表。现在我们希望对结果进行进一步过滤,比如返回标题含有关键词 django 的文章资源列表。

我们到底该怎么做呢? 本例中我将演示三种方法, 你可以根据实际项目开发需求去使用。

重写 GenericsAPIView 

或 viewset 的 get_queryset 方法

此方法不依赖于任何第三方包, 只适合于需要过滤的字段比较少的模型。

比如这里我们需要对文章 title 进行过滤,我们只需要修改 ArticleList 视图函数类即可。

# blog/views.pyfrom rest_framework import generics
from rest_framework import permissions
from .permissions import IsOwnerOrReadOnly
from .pagination import MyPageNumberPaginationclass ArticleList(generics.ListCreateAPIView):serializer_class = ArticleSerializerpermission_classes = (permissions.IsAuthenticatedOrReadOnly,)pagination_class = MyPageNumberPaginationdef get_queryset(self):keyword = self.request.query_params.get('q')if not keyword:queryset = Article.objects.all()else:queryset = Article.objects.filter(title__icontains=keyword)return queryset# associate user with article author.def perform_create(self, serializer):serializer.save(author=self.request.user)

修改好视图类后,发送 GET 请求到 /v1/articles?page=2&q=django, 你将得到所有标题含有 django 关键词的文章列表,这里显示一共有 3 条结果。

当一个模型需要过滤的字段很多且不确定时(比如文章状态、正文等等), 重写 get_queryset 方法将变得非常麻烦,更好的方式是借助 django-filter 这个第三方库实现过滤。

使用 django-filter

django-filter 库包含一个 DjangoFilterBackend 类,该类支持 REST 框架的高度可定制的字段过滤。自定义需要过滤的字段非常方便, 还可以对每个字段指定过滤方法(比如模糊查询和精确查询)。具体使用方式如下:

2.1 安装 django-filter

pip install django-filter

2.2  把 django_filters 添加到 INSTALLED_APPS

INSTALLED_APPS = [...,django_filters,
]

2.3 自定义 FilterSet 类。

这里我们自定义了按标题关键词和文章状态进行过滤。

# blog/filters.py(新建)

import django_filters
from .models import Articleclass ArticleFilter(django_filters.FilterSet):q = django_filters.CharFilter(field_name='title', lookup_expr='icontains')class Meta:model = Articlefields = ('title', 'status')

2.4 将自定义 FilterSet 类加入到 View 类或 ViewSet,另外还需要将 DjangoFilterBackend 设为过滤后台.如下所示:

# New for django-filter
from django_filters import rest_framework
from .filters import ArticleFilterclass ArticleList(generics.ListCreateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializerpermission_classes = (permissions.IsAuthenticatedOrReadOnly,)pagination_class = MyPageNumberPagination# new: filter backends and classesfilter_backends = (rest_framework.DjangoFilterBackend,)filter_class = ArticleFilter# associate request.user with author.def perform_create(self, serializer):serializer.save(author=self.request.user)

发送 GET 请求到 /v1/articles?page=2&q=django&status=p, 你将得到如下返回结果,只包含发表了的文章。

你还可以看到 REST 框架提供了一个新的 Filters 下拉菜单按钮,可以帮助您对结果进行过滤(见上图标红部分)。

使用 DRF 提供的 SearchFilter 类

其实 DRF 自带了具有过滤功能的 SearchFilter 类,其使用场景与 Django-filter 的单字段过滤略有不同,更侧重于使用一个关键词对模型的某个字段或多个字段同时进行搜索。

使用这个类,你还需要指定 search_fields, 具体使用方式如下:

from rest_framework import filtersclass ArticleList(generics.ListCreateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializerpermission_classes = (permissions.IsAuthenticatedOrReadOnly,)pagination_class = MyPageNumberPagination# new: add SearchFilter and search_fieldsfilter_backends = (filters.SearchFilter, )search_fields = ('title',)# associate request.user with author.def perform_create(self, serializer):serializer.save(author=self.request.user)

发送 GET 请求到 /v1/articles?page=1&search=django, 你将得到如下结果。

注意:这里进行搜索查询的默认参数名为 ?search=xxx。

SearchFilter 类非常有用,因为它不仅支持对模型的多个字段进行查询,还支持 ForeinKey 和 ManyToMany 字段的关联查询。

按如下修改 search_fields, 就可以同时搜索标题或用户名含有某个关键词的文章资源列表。修改好后,作者用户名里如果有 django,该篇文章也会包含在搜索结果了。

search_fields = ('title', 'author__username')

默认情况下,SearchFilter类搜索将使用不区分大小写的部分匹配(icontains)。你可以在 search_fields 中添加各种字符来指定匹配方法。

  • '^'开始 - 搜索。

  • '='完全匹配。

  • '@'全文搜索。

  • '$'正则表达式搜索。

例如:search_fields = ('=title', )精确匹配 title。

前面我们详细介绍了对结果进行过滤的 3 种方法,接下来我们再看看如何对结果进行排序,这里主要通过 DRF 自带的 OrderingFilter 类实现

使用 DRF 的 OrderingFilter 类

使用 OrderingFilter 类首先要把它加入到 filter_backends, 然后指定排序字段即可,如下所示:

from rest_framework import filtersclass ArticleList(generics.ListCreateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializerpermission_classes = (permissions.IsAuthenticatedOrReadOnly,)pagination_class = MyPageNumberPaginationfilter_backends = (filters.SearchFilter, filters.OrderingFilter,)search_fields = ('title',)ordering_fields = ('create_date')

发送请求时只需要在参数上加上?ordering=create_date 或者?ordering=-create_date 即可实现对结果按文章创建时间正序和逆序进行排序。

点击 DRF 界面上的 Filters 按钮,你还会看到搜索和排序的选项。

注:实际开发应用中 OrderingFilter 类,SearchFilter 类和 DjangoFilterBackend 经常一起联用作为 DRF 的 filter_backends,没有相互冲突。

更多精彩推荐
☞告别 Windows、Android,国产操作系统合力破局☞那些追源码的平凡之路☞Windows 游戏之父 Eric Engstrom 意外去世,享年55岁☞苹果 M1 芯片预示着 RISC-V 完全替代 ARM?
☞管理大型共享数据库,做到这几点不再头疼!
☞弃用 Cookie!☞前端诸神大战,Vue、React 依旧笑傲江湖点分享点点赞点在看

如何在 Django REST Framework 中对分页结果过滤和排序?相关推荐

  1. 【接口文档】Django restful framework中自动生成API文档

    Django restful framework中自动生成API文档 一.Swagger概述 1.引言 当接口开发完成,紧接着需要编写接口文档.传统的接口文档使用Word编写,or一些接口文档管理平台 ...

  2. 解决Django Rest Framework中的跨域问题

    解决Django Rest Framework中的跨域问题 参考文章: (1)解决Django Rest Framework中的跨域问题 (2)https://www.cnblogs.com/qicu ...

  3. Django REST Framework中的Serializer relations

    官方文档原文 Relational fields are used to represent model relationships. They can be applied to ForeignKe ...

  4. 在ASP.NET MVC5中实现具有服务器端过滤、排序和分页的GridView

    背景 在前一篇文章<[初学者指南]在ASP.NET MVC 5中创建GridView>中,我们学习了如何在 ASP.NET MVC 中实现 GridView,类似于 ASP.NET web ...

  5. 在django restful framework中设置django model的property

    众所周知,在django的model中,可以某些字段设置@property和setter deleter getter,这样就可以在存入数据的时候进行一些操作,具体原理请参见廖雪峰大神的博客https ...

  6. JWT验证机制【刘新宇】【Django REST framework中使用JWT】

    JWT 在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证.我们不再使用Session认证机制,而使用Json Web Token认证机制. 什么是JWT Json web t ...

  7. jpa 分页 排序 过滤_使用JPA标准@ViewScoped通过分页,过滤和排序进行Primefaces DataTable延迟加载...

    jpa 分页 排序 过滤 Primefaces数据表惰性分页有效,但是在Web上使用Criteria搜索完整示例后,我感到非常沮丧. 所以我混合了来自 http://stackoverflow.com ...

  8. 使用JPA标准@ViewScoped通过分页,过滤和排序进行Primefaces DataTable延迟加载

    Primefaces数据表惰性分页有效,但是在Web上使用Criteria搜索完整示例后,我感到非常沮丧. 所以我混合了来自 http://stackoverflow.com/questions/13 ...

  9. DRF (Django REST framework) 中的视图类

    视图说明 1. 两个基类 1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父 ...

最新文章

  1. 做为程序员对sql进行的性能优化
  2. ES6新特性_ES6模板字符串---JavaScript_ECMAScript_ES6-ES11新特性工作笔记007
  3. testNG-失败用例重跑机制
  4. Google Jump Consistent Hash 一致性哈希算法
  5. 【智驾深谈】想拿自动驾驶融资,先过VC这16问
  6. python按键精灵是哪个库_按键精灵命令库的介绍和使用
  7. Swagger2自定义添加请求头key-value暴力猴插件
  8. 《Ruminations on C++/C++沉思录》学习笔记一————koening和Moo夫妇访谈
  9. win10系统迁移后系统重装_Win10技巧:Windows 10系统迁移方法!
  10. 手机怎么查看视频的MD5
  11. lua 函数 默认值_简明lua教程
  12. Quartus ii 中ROM ip核的应用
  13. 教你自制一款简单的助听器
  14. 最近ChatGPT封号太严重了,这里是解封攻略步骤(建议收藏)
  15. 给自学者的建议:想学游戏编程开发,你需要做什么?
  16. java核心之类和对象
  17. Android native层Hander原理分析
  18. 使用 cURL 进行 HTTP 请求实例
  19. mongo的基本操作
  20. 基本器件选型之二极管

热门文章

  1. Eclipse选择哪个版本
  2. stderr和stdout详细解说
  3. 基于DVWA的CSRF
  4. Postgres 数据库字符集更改 ERROR: new encoding (UTF8) is incompatible
  5. [01] 四大组件之Activity
  6. Github官方app分析——用户身份验证模块
  7. 杀不死的人狼——我读《人月神话》(四)
  8. [C/C++] 按行读取文件
  9. [FFmpeg] RGBA 和 YUV 存储方式
  10. html轮播图向左改为向下,jQuery之轮播图向左滚动动画【原创】