Django REST framework数据展示技巧:分页、过滤与搜索的实用配置与实践

简介: Django REST framework数据展示技巧:分页、过滤与搜索的实用配置与实践

前言

    在本篇博客中,我们将详细解析Django REST framework中分页、过滤和搜索的定义、功能以及使用方法。我们不仅会介绍如何进行基本的设置和使用,还会深入探讨如何进行全局配置和局部配置,以满足不同场景下的需求。

    分页功能 允许我们根据需求将数据划分为多个页面,确保用户在浏览大量数据时不会感到混乱或过载。过滤功能 则赋予了用户更精细地控制所看到数据的能力,通过预设条件或自定义查询,用户可以快速定位到所需信息。而搜索功能 则进一步增强了这种能力,让用户能够通过关键词迅速检索到相关数据。


一、分页

    试想一下,为什么我们几乎不在网页中一次性展示请求获得的所有数据呢?

  • 如果这个数据量相当小,比如只有几十条,那么一般情况下无需担心,一股脑渲染到页面中就行。
  • 但如果这个数据量比较大,比如几百几千几万条,且一旦这种操作比较频繁,显然就会增加服务器负载,主要瓶颈是数据库。

  这里不谈如何实现高并发,只谈如何以轻量化的方式获取并展示数据。


一种有效的方式就是实现分页查询

将一次性获取所有数据的操作,分解为多次查询操作,每次操作只查询并展示一部分数据。其中每一次查询就是获取一页数据。

效果如下:

1. Django视图函数中实现分页

django视图函数中实现分页效果:

#views.py
# 0.视图函数实现分页效果
def index(request):
    if request.method == 'POST':
        return JsonResponse({"message":"POST测试列表分页"})
        # return HttpResponse('{"message":"Hello POST"}',content_type='application/json')
    elif request.method == 'GET':
        list1 = ["张三","李四","王五","赵六","立秋","李琦","离奇",64,84,84,6,54,5,6,7]
        # Paginator(列表数据,条数)
        pagtor = Paginator(list1,3)
        # 获取前端的查询参数:请求页数,页码
        page = request.GET.get('page')
        print(page)
        data = pagtor.get_page(page)
        print(data.object_list)
        # return HttpResponse('{"message": data.object_list}',content_type='application/json')
        return JsonResponse({"message":"测试GET列表分页",'data': data.object_list})
        

注意:

JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)

JsonResponseHttpRespon的子类, 它主要和父类的区别在于:

  • 它的默认Content - Type被设置为: application/json
  • 第一个参数, data应该是一个字典类型, 当safe这个参数被设置为: False, 那data可以填入任何能被转换为JSON格式的对象, 比如list, tuple, set.
  • 默认的safe参数是True,如果你传入的data数据类型不是字典类型, 那么它就会抛出TypeError的异常

2. DRF全局设置分页

注意:需要修改Django的全局配置文件 settings.py

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 3 #每页数据条数
}
#views.py
class IndexView(ListAPIView):
    queryset = StudentModel.objects.all()
    serializer_class = StudentSerializer

3. DRF局部设置分页

DRF自定义分页类对象并进行局部分页设置:

#views.py
#导入分页器类
from rest_framework.pagination import PageNumberPagination
# 局部分页配置  自定义分页器
class MyPaginator(PageNumberPagination):
    page_size = 2 # 每页数量
    page_query_param = 'page' #查询参数:页码的参数名
    page_size_query_param = 'page_size' #查询参数,每页数量的参数名
    max_page_size = 10 #每页最大数量
# http://localhost:8000/app01/indexview/?page=1&page_size=10
# 1.DRF 分页
class IndexView(ListAPIView):
    queryset = StudentModel.objects.all()
    serializer_class = StudentSerializer
    pagination_class = MyPaginator

4. 在APIView 中使用分页

前面的使用内置分页的视图函数都需要继承 GenericAPIView、ListModelMixin(或者直接继承ListAPIView),如果在正常的APIview中,如何实现自定义分页呢?

    其实步骤是一样的,只不过APIView中没有提供数据和方法的封装,所有的操作,需要手动完成,下面我们可以自己编写继承 APIView 的视图函数实现分页。

class IndexView(APIView):
    def get(self,request):
        users = UserModel.objects.all()
        
        # 对数据集进行分页,自定义的分页器
        # paginator = CommonPageNumberPagination()
        #加载系统分页器
        paginator = PageNumberPagination()
        
        #局部设置,配置对应page_size大小和对应参数key
        paginator.page_size = 2
        
        # 获取分页过后的数据
        qs = paginator.paginate_queryset(users, request, self)
        
        # 对数据进行序列化,多条数据需要添加 many=True
        res = UserSer(qs, many=True)
        
    # 返回的方式一,只返回分页后的结果
        # return Response(res.data)
        
        # 返回方式二,自己配置返回的其他信息,例如上一页下一页
        # return Response({
        #     'count': books.count(),
        #     'next': paginator.get_next_link(),
        #     'previous': paginator.get_previous_link(),
        #     'results': res.data
        # })
        
        # 返回方式三,使用方法自动返回类似于方式二的内容
        return paginator.get_paginated_response(res.data)

二、过滤

在 Django 中,django-filter 是一个强大的第三方应用,它提供了一种简单、灵活且可定制的过滤器系统,允许开发者轻松地对 Django 查询集进行过滤和排序。

过滤器 允许用户根据特定的条件来筛选数据。在 Django 中,这通常意味着对查询集(QuerySet)进行过滤。

1. django-filter的精准过滤

使用步骤

  • 安装插件

django-filter库包含一个DjangoFilterBackend类,该类支持针对REST框架的高度可自定义的字段筛选。

要使用DjangoFilterBackend,请先安装django-filter

pip install django-filter
  • 注册APP

添加'django_filters'到Django的INSTALLED_APPS

#settings.py
INSTALLED_APPS = [
    ...
    'django_filters',
    ...
]
  • 配置过滤引擎

将过滤器后端添加到全局设置中:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}

全局配置 精确过滤

import django_filters.rest_framework
from rest_framework.generics import ListAPIView
from app.models import StudentModel
from app.serializer.studentSerializer import StudentSerializer
# 1. 精确过滤
class IndexFilterViews(ListAPIView):
    queryset = StudentModel.objects.all()
    serializer_class = StudentSerializer
    
    filterset_fields = ['name','gender']
# 过滤
# http://localhost:8000/app01/indexfilter/?name=张三
# http://localhost:8000/app01/indexfilter/?name=张三&gender=1

局部配置 精确过滤

import django_filters.rest_framework
from rest_framework.generics import ListAPIView
from app.models import StudentModel
from app.serializer.studentSerializer import StudentSerializer
# 局部配置 过滤
from django_filters.rest_framework import DjangoFilterBackend
# 1. 精确过滤
class IndexFilterViews(ListAPIView):
    queryset = StudentModel.objects.all()
    serializer_class = StudentSerializer
    filter_backends = [DjangoFilterBackend] 
    filterset_fields = ['name','gender']
# 过滤
# http://localhost:8000/app01/indexfilter/?name=张三
# http://localhost:8000/app01/indexfilter/?name=张三&gender=1

2. django-filter的模糊过滤

默认的过滤器可以实现精准搜索功能,但是对于有些字段或者数据,在开发过程中需要实现模糊过滤,那么就需要进行过滤器的自定义实现,自定义一个高级过滤器,下面是 自定义过滤器

模糊过滤

# views_filter.py
import django_filters.rest_framework
from rest_framework.generics import ListAPIView
from app.models import StudentModel
from app.serializer.studentSerializer import StudentSerializer
# 局部配置 过滤
from django_filters.rest_framework import DjangoFilterBackend
# 过滤器
# 2. 模糊过滤
class StudentFilter(django_filters.rest_framework.FilterSet):
  """自定义过滤器类"""
    name = django_filters.CharFilter(field_name='name', lookup_expr='contains') 
    # field_name 表示要过滤字段;lookup_expr 表示 过滤时要进行的操作,
    # contains 表示 包含,用来进行模糊过滤
    
    maxgt_age = django_filters.NumberFilter(field_name='age', lookup_expr='gte')
    minlt_age = django_filters.NumberFilter(field_name='age', lookup_expr='lte')
    class Meta:
        model = StudentModel
        fields = ['name','maxgt_age','minlt_age'] #查询参数,与数据库无关
class StudentVagueFilter(ListAPIView):
    queryset = StudentModel.objects.all()
    serializer_class = StudentSerializer
    filter_backends = [DjangoFilterBackend] # 局部配置 过滤
    filterset_class = StudentFilter # 指明过滤器类
http://127.0.0.1:8000/app/students/?name=李

3. rest_framework的SearchFilter

rest_frameworkSearchFilter 是 Django REST framework 提供的一个过滤器后端类,专门用于在 API 视图中执行文本搜索过滤。

SearchFilter 允许用户在查询字符串中通过特定的参数(默认为 search)来搜索数据。这个过滤器基于数据库的全文搜索功能(如果可用),在指定的字段上执行全文搜索,并返回匹配指定搜索词的结果。

该搜索引擎依赖于 rest_framework, 不需要安装额外的插件

  • 配置搜索引擎

将过滤器后端添加到全局设置中:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter']
}

局部配置 / 全局配置 搜索:

from rest_framework.generics import ListAPIView
from app.models import StudentModel
from app.serializer.studentSerializer import StudentSerializer
# 局部配置 搜索
#from rest_framework.filters import SearchFilter
class IndexSearchView(ListAPIView):
    queryset = StudentModel.objects.all()
    serializer_class = StudentSerializer
    # 局部配置 搜索
    # filter_backends = [SearchFilter]
    
    search_fields = ['name']
    # search_fields = ['^name'] 姓name的
    # search_fields = ['=name'] 完全匹配,为name的
    ordering_fields = ['age']
http://127.0.0.1:8000/app/index/?search=张三

PS:可以通过在字符前面添加各种字符来限制搜索行为search_fields:

  • '^'开始搜索
  • '='完全匹配
  • '$'正则表达式搜索

三、排序

使用Ordering-Filter实现排序

将获取的数据按照一定的字段要求顺序进行排序,其实在model 模型类中也可以定义ordering 字段实现,排序实现其实还是用到了过滤部分的功能

实现排序要使用DRF 提供的OrderingFilter 实现

设置 过滤器后端(两种方式)

# 1.全局配置时--settings.py
REST_FRAMEWORK = {
 
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter']
}
# 2.局部配置时---views_search.py 
  # 导入
  from rest_framework.filters import SearchFilter,OrderingFilter
  #视图 内部 (完整代码在下个代码块)
  filter_backends = [filters.OrderingFilter]

views_search.py 完整代码如下:

# views_search.py
from rest_framework.generics import ListAPIView
from app.models import StudentModel
from app.serializer.studentSerializer import StudentSerializer
# 局部配置(导包)  搜索
from rest_framework.filters import SearchFilter,OrderingFilter
class IndexSearchView(ListAPIView):
    queryset = StudentModel.objects.all()
    serializer_class = StudentSerializer
    
    # 局部配置时要设置filter_backends ,全局配置过就不用了
    # filter_backends = [SearchFilter]
    filter_backends = [SearchFilter,OrderingFilter]
    
    search_fields = ['name']
    # search_fields = ['^name'] 以name开头的,姓 name的
    # search_fields = ['=name'] 完全匹配,为 name的
    ordering_fields = ['age']
http://127.0.0.1:8000/app/indexsearch/?ordering=-age # 从大到小
http://127.0.0.1:8000/app/indexsearch/?ordering=age # 从小到大
相关文章
|
2月前
|
存储 缓存 NoSQL
深入理解Django与Redis的集成实践
深入理解Django与Redis的集成实践
78 0
|
1月前
|
SQL 监控 数据库
深入探索Django ORM:高效数据操作的秘诀与实践####
在当今的Web开发领域,提升数据访问层的效率是优化应用性能的关键。本文旨在通过剖析Django框架中的ORM(对象关系映射)机制,揭示其如何简化数据库交互,并探讨一系列高级技巧与策略,帮助开发者构建更高效、可维护的数据访问代码。我们不涉及安装步骤或基础概念,而是聚焦于实战经验分享,旨在为中高级开发者提供深度洞见。 ####
|
2月前
|
JavaScript 前端开发 Python
django接收前端vue传输的formData图片数据
django接收前端vue传输的formData图片数据
62 4
|
2月前
|
关系型数据库 MySQL Java
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
这篇文章是关于如何使用Django框架配置MySQL数据库,创建模型实例,并自动或手动创建数据库表,以及对这些表进行操作的详细教程。
87 0
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
|
2月前
|
数据库 数据安全/隐私保护 数据库管理
#765372#基于django和neo4j的通用数据展示系统
#765372#基于django和neo4j的通用数据展示系统
27 1
|
2月前
|
搜索推荐 关系型数据库 MySQL
#874358#基于django/neo4j的电视剧浏览数据推荐系统
#874358#基于django/neo4j的电视剧浏览数据推荐系统
31 0
|
4月前
|
前端开发 关系型数据库 Python
Django入门到放弃之分页器
Django入门到放弃之分页器
|
4月前
|
负载均衡 应用服务中间件 网络安全
Django后端架构开发:Nginx服务优化实践
Django后端架构开发:Nginx服务优化实践
67 2
|
4月前
|
API 数据库 开发者
【独家揭秘】Django ORM高手秘籍:如何玩转数据模型与数据库交互的艺术?
【8月更文挑战第31天】本文通过具体示例详细介绍了Django ORM的使用方法,包括数据模型设计与数据库操作的最佳实践。从创建应用和定义模型开始,逐步演示了查询、创建、更新和删除数据的全过程,并展示了关联查询与过滤的技巧,帮助开发者更高效地利用Django ORM构建和维护Web应用。通过这些基础概念和实践技巧,读者可以更好地掌握Django ORM,提升开发效率。
47 0
|
4月前
|
JSON API 数据安全/隐私保护
哇塞!Django REST framework 太逆天啦!构建 API 服务从未如此轻松,你还不来试试?
【8月更文挑战第31天】Django REST framework(DRF)是基于Django框架的高效Web API开发工具,提供序列化、视图集、路由等功能,简化API构建流程。使用DRF可轻松实现数据的序列化与反序列化,并支持权限管理和认证机制以保障API安全。安装DRF只需通过`pip install djangorestframework`命令。要创建基本项目,先安装Django并创建新应用,定义模型、序列化器及视图集,最后配置路由。测试API时,可通过Postman发送HTTP请求验证功能。无论项目大小,DRF均能提供强大支持。
48 0