QNIT.NET

  • Windows系统
  • 系统硬件
  • Mac系统
  • Linux系统
  • 虚拟系统
  • 编程技术
  1. 首页
  2. 编程技术
  3. 正文

【Python】利用Django搭建REST风格API后台服务(三)关于DRF的搜索、分页、排序

2019-12-10 983 0 0

简介

这是第三篇内容,接下来我们介绍一下如何使用REST framework框架自带的一些功能来丰富你的API。

我们都知道利用API获取资源的场景下,不止是傻傻的查询所有数据,然后对数据进程采集。我们如果要按照要求来筛选我们要的数据呢?

比如,我们不想要一次显示这么多条数据,我们在前台不需要加载这么多。或者,我们需要有条件的去筛查数据,或者有顺序的去取数据。

这些在REST framework都已经帮你把功能设计好了,只需要引用和稍作定制就可以使用了。

我们分别来简单的介绍一下REST framework的分页、搜索、排序的使用方法。

实验我们还是拿上次试验的那个Student类来做这次的实验。

分页

我们在实际开发当中,不可能直接一个视图下显示所有的数据,一般web端会用分页来划分,而手机端一般是用“上拉加载”的办法来进行新增数据的操作。这样的操作无疑是减轻了前后台两端对数据库操作的工作量,让用户需要吃多少就拿多少,不会造成大量的资源浪费。

REST framework为我们提供了比较不错的分页功能,

全局分页

分页的方式有分两种,一种是全局设置,在setting.py下配置即可设置全局分页的功能。

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination'
}

分类中有许多属性可以自己设置。网上有位大佬整理的很不错,大家可以看看他写的内容。

PageNumberPagination类包括可以覆盖以修改分页样式的许多属性,要设置这些属性,应覆盖PageNumberPagination类,然后如上所示启用自定义分页类。

django_paginator_class:使用的Django Paginator类,默认是django.core.paginator.Paginator,对大部分用例是适用的。

page_size:数值,页面大小,默认是全局PAGE_SIZE的值。

page_query_param:字符串,查询参数的名称,默认是'page'page_size_query_param:字符串,请求设置页面大小的参数名称,默认是None,表示客户端可能无法控制请求的页面大小。

max_page_size:字符串,最大允许请求的页面大小, 此属性仅在page_size_query_param也被设置时有效。

last_page_strings:字符串列表或者元组,默认是('last',)template:分页控件使用的模板的名称,可以覆盖或设置为None,默认为"rest_framework/pagination/numbers.html"

设置完全局分页后,只需要输入URL的形式就可以访问

http://127.0.0.1:8000/api/student/?page=2

自定义分页

当然,这里我们更推荐的是自定义分页的方法,毕竟这种方法毕竟灵活。在实际开发当中,也不是所有的资源都需要进行分页的,或者不是所有资源都是一样的分页属性,有的一页10条,有的一页只需要3条,这样该怎么做呢?

我们先在views.py下定义好一个分页的配置:

# 记得要导包啊
from rest_framework import viewsets,filters,pagination

class PageSet(pagination.PageNumberPagination):
    # 每页显示多少个
    page_size = 3
    # 默认每页显示3个
    page_size_query_param = "size"
    # 最大页数
    max_page_size = 10
    # 获取页码数的
    page_query_param = "page"

然后我们在我们之前定义好的Viewsets类下使用它即可

class StudentViewSet(viewsets.ModelViewSet):
    # 指定结果集并设置排序
    queryset = Student.objects.all().order_by('-pk')
    # 指定序列化的类
    serializer_class = StudentSerializers
    # 指定分页配置
    pagination_class = PageSet

运行项目查看视图,是不是又变了?

可以看到右上角多了分页的按钮可以进行分页。当然也可以通过URL来进行访问分页后的内容:

http://127.0.0.1:8000/api/student/?page=1

可以看到,返回的结果集也和之前不一样了:

{
    "count": 5,
    "next": "http://127.0.0.1:8000/api/student/?page=2",
    "previous": null,
    "results": [
    {
        "pk": 6,
        "name": "煞笔啊",
        "sex": "male",
        "sid": "0"
    },
    {
        "pk": 4,
        "name": "小明",
        "sex": "???",
        "sid": "113"
    },
    {
        "pk": 3,
        "name": "小王八",
        "sex": "男",
        "sid": "112"
    }
]
}

—

count是该资源下的所有资源的数量。

next是下一页的URL,这个非常重要,在许多场景下会使用得到。

previous则是上一页,也是一个重要的功能

results则是我们的结果集了。

这样一来简单的自定义分页就写好了,有的同学可能要问了,在一些特殊的场景下,比如我临时查找的数据为5条而不是默认设置的3条,该怎么查呢?

很简单,我们在URL参数内设置好参数传入即可,如下:

http://127.0.0.1:8000/api/student/?page=1&size=5

这样就可以把size设置为5进行分页查找。是不是很方便?

按照资源对应的位置

我们在其他的场景下,可能会需要访问到,第x个资源的那页,就是按照位置来定位某一页的内容。

比如我们一页设置3个资源,我们需要访问第4个资源的那页,也就是第二页。

这样该如何来写?参考下面代码:

class LimitSet(pagination.LimitOffsetPagination):
    # 每页默认几条
    default_limit = 3
    # 设置传入页码数参数名
    page_query_param = "page"
    # 设置传入条数参数名
    limit_query_param = 'limit'
    # 设置传入位置参数名
    offset_query_param = 'offset'
    # 最大每页显示条数
    max_limit = None

使用方法和上一步一样

class StudentViewSet(viewsets.ModelViewSet):
    # 指定结果集并设置排序
    queryset = Student.objects.all().order_by('-pk')
    # 指定序列化的类
    serializer_class = StudentSerializers
    #指定分页配置
    pagination_class = LimitSet

输入URL就按照位置来查询了,比如查询每页3条、第4条的位置所在的分页情况

http://127.0.0.1:8000/api/student/?limit=3&offset=4

常用的分页功能暂时讲到这里吧

搜索功能

搜索功能可以说是当下必备的一个功能了,他用来检索和过滤用户所需要的信息。

搜索的实现方法非常多,REST framework有提供了一个相对比较简洁的搜索功能给我们使用。打开views.py来里的定义好的viewsets类来设置搜索功能吧。

# 记得要导包啊
from rest_framework import viewsets,filters,pagination

class StudentViewSet(viewsets.ModelViewSet):
    # 指定结果集并设置排序
    queryset = Student.objects.all().order_by('-pk')
    # 指定序列化的类
    serializer_class = StudentSerializers
    # 指定分页配置
    pagination_class = LimitSet
    # 配置搜索功能
    filter_backends = (filters.SearchFilter,)
    # 设置搜索的关键字
    search_fields = ('=name','sid')

这里指的注意的是,在search_fields这个元组中,我们设置需要过滤的字段分别为姓名name和学号sid。

我们可以发现视图右上角多了一个filter的按钮,点击可以进行搜索

可以说非常贴心了

搜索的URL也很简单。

http://example.com/list/?search=?search=keyword

姓名这样写:=name 表示完全匹配。例如我写小王,只能搜到小王,不能搜到小王八。

http://127.0.0.1:8000/api/student/?search=?search=小王

{
"count": 1,
"next": null,
"previous": null,
"results": [
        {
            "pk": 2,
            "name": "小王",
            "sex": "女",
            "sid": "110"
        }
    ]
}

而学号在不加任何修饰符下,是模糊搜索,只有搜索内容中有相关的字符串都会被抓取出来。下载我们尝试搜索一下学号带有 1 的学生。

http://127.0.0.1:8000/api/student/?search=1

{
"count": 4,
"next": "http://127.0.0.1:8000/api/student/?limit=3&offset=3&search=1",
"previous": null,
"results": [
        {
            "pk": 4,
            "name": "小明",
            "sex": "???",
            "sid": "113"
        },
        {
            "pk": 3,
            "name": "小王八",
            "sex": "男",
            "sid": "112"
        },
        {
            "pk": 2,
            "name": "小王",
            "sex": "女",
            "sid": "110"
            }
    ]
}

修饰符有以下几种大家根据实际需求来选择使用:

    ^ :搜索关键字开头的数据
    = :完全匹配搜索
    @ :全文搜索(目前只支持MySQL)
    $ :正则表达式搜索

简单的检索功能介绍就到此为止了。

排序功能

排序功能在数据量大的情况下便显得非常有用了。我们在第一篇中有提到的默认排序,但是在未来的开发中,还有其他的需求在等着我们。比如拿这个Student类来说,我们需要对学生做排序,让学生以姓名、学号、班级、成绩等熟悉来进行有效的排序。该怎么做?

还是打开views.py下定义好的viewsets类进行添加代码

class StudentViewSet(viewsets.ModelViewSet):
    # 指定结果集并设置排序
    queryset = Student.objects.all().order_by('-pk')
    # 指定序列化的类
    serializer_class = StudentSerializers
    # 指定分页配置
    pagination_class = PageSet
    # 配置搜索功能和排序功能
    filter_backends = (filters.SearchFilter,filters.OrderingFilter,)
    # 设置搜索的关键字
    search_fields = ('=name','sid')
    # 设置需要被排序的字段
    ordering_fields = ('name', 'sid')

注意filter_backends元组下要添加filters.OrderingFilter才能实现排序功能

配置完毕后。我们这边对name和sid两个字段注册了排序的功能,这时就可以通过视图或者URL来进行排序查询了。

  http://127.0.0.1:8000/api/student/?ordering=name&size=10

  为了方便查看更多结果,这边我们把分页数量的属性设置成10条。
  利用学生姓名字段来进行排序,原来默认的是利用主键pk来排序的。

   {
    "count": 5,
    "next": null,
    "previous": null,
    "results": [
        {
            "pk": 4,
            "name": "小明",
            "sex": "???",
            "sid": "113"
        },
        {
            "pk": 2,
            "name": "小王",
            "sex": "女",
            "sid": "110"
        },
        {
            "pk": 3,
            "name": "小王八",
            "sex": "男",
            "sid": "112"
        },
        {
            "pk": 1,
            "name": "小红",
            "sex": "男",
            "sid": "111"
        },
        {
            "pk": 6,
            "name": "煞笔啊",
            "sex": "male",
            "sid": "0"
        }
    ]
}

结果出来了,排序分为两种:升序和降序,使用方法就是在字段前面加不加”-“号的区别而已,非常简洁方便。

这已经是第三篇了。还有一些功能下次会继续提出来,比如如何使用api进行多表联查等功能。

其实有了这些功能以及足够搭建一个微小的服务平台了。

接下去有时间我会更新一下实战项目,比如制作一套前后台分离的系统,前台分别用web端和android端来实现。

标签: API Django
最后更新:2021-11-24

leon

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

取消回复
最新 热点 随机
最新 热点 随机
清理 Docker 占用的磁盘空间 CSS常用命名名称 常用正则表达式速查手册,Python文本处理必备 SAS硬盘指示灯状态对照表 电脑的基础认识(硬件篇) 将照片变成漫画风格
安装macOS Mojave提示”这个安装macos应用程序副本已损坏“ CSS常用命名名称 VirtualBox虚拟机后台运行 基于django的rest api快速开发(只提供一个接口服务) ESXI的磁盘映射操作 黑苹果系统MacOS 10.14 Mojave硬件支持列表
标签聚合
Mojave API Navicat JWT Django 虚拟系统 ESXI MySql

COPYRIGHT © 2021 QNIT.NET. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY Qnit.net

黔ICP备2021010068号

贵公网安备 52270102000278 号