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

07-14 1287阅读

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

系列文章目录

  • Django入门全攻略:从零搭建你的第一个Web项目
  • Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作
  • Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解
  • Django ORM深度游:探索多对一、一对一与多对多数据关系的奥秘与实践
  • 跨域问题与Django解决方案:深入解析跨域原理、请求处理与CSRF防护
  • Django视图层探索:GET/POST请求处理、参数传递与响应方式详解
  • Django路由与会话深度探索:静态、动态路由分发,以及Cookie与Session的奥秘
  • Django API开发实战:前后端分离、Restful风格与DRF序列化器详解
  • Django REST framework序列化器详解:普通序列化器与模型序列化器的选择与运用
  • Django REST framework关联序列化器详解:掌握复杂关系的序列化与反序列化艺术
  • Django REST framework中GenericAPIView与混入扩展类详解
  • Django REST framework视图集与路由详解:深入理解ViewSet、ModelViewSet与路由映射器
  • Django中间件探索:揭秘中间件在Web应用中的守护角色与实战应用
  • Django REST framework数据展示技巧:分页、过滤与搜索的实用配置与实践
  • 努力学习0.0ing…

    文章目录

    • 系列文章目录
    • 前言
    • 一、分页
      • 1. Django视图函数中实现分页
      • 2. DRF全局设置分页
      • 3. DRF局部设置分页
      • 4. 在APIView 中使用分页
      • 二、过滤
        • 1. django-filter的精准过滤
        • 2. django-filter的模糊过滤
        • 3. rest_framework的SearchFilter
        • 三、排序
          • 使用Ordering-Filter实现排序

            前言

                在本篇博客中,我们将详细解析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)

              JsonResponse是HttpRespon的子类, 它主要和父类的区别在于:

              • 它的默认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_framework 的 SearchFilter 是 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 # 从小到大
                          

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

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]