zoukankan      html  css  js  c++  java
  • drf过滤器、筛选器、分类器、搜索器、分页器(各种组件等)

    过滤器(组件)使用

    群查接口各种筛选、过滤数据准备

    models.py

    # 数据库表数据
    class Course(BaseModel):
        """课程"""
        course_type = (
            (0, '付费'),
            (1, 'VIP专享'),
            (2, '学位课程')
        )
        level_choices = (
            (0, '初级'),
            (1, '中级'),
            (2, '高级'),
        )
        status_choices = (
            (0, '上线'),
            (1, '下线'),
            (2, '预上线'),
        )
        name = models.CharField(max_length=128, verbose_name="课程名称")
        course_img = models.ImageField(upload_to="courses", max_length=255, verbose_name="封面图片", blank=True, null=True)
        course_type = models.SmallIntegerField(choices=course_type, default=0, verbose_name="付费类型")
        # 使用这个字段的原因
        brief = models.TextField(max_length=2048, verbose_name="详情介绍", null=True, blank=True)
        level = models.SmallIntegerField(choices=level_choices, default=0, verbose_name="难度等级")
        pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True)
        period = models.IntegerField(verbose_name="建议学习周期(day)", default=7)
        attachment_path = models.FileField(upload_to="attachment", max_length=128, verbose_name="课件路径", blank=True,
                                           null=True)
        status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="课程状态")
        course_category = models.ForeignKey("CourseCategory", on_delete=models.SET_NULL, db_constraint=False, null=True, blank=True,
                                            verbose_name="课程分类")
        students = models.IntegerField(verbose_name="学习人数", default=0)
        sections = models.IntegerField(verbose_name="总课时数量", default=0)
        pub_sections = models.IntegerField(verbose_name="课时更新数量", default=0)
        price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价", default=0)
        teacher = models.ForeignKey("Teacher", on_delete=models.DO_NOTHING, null=True, blank=True, verbose_name="授课老师")
        orders = models.IntegerField(default=0)
    	# 自定义插拔式字段
        @property
        def level_name(self):
            return self.get_level_display()
    	# 连表查询
        @property
        def section_list(self):
            temp_section_list = []
            for chapter in self.coursechapters.all():
                for section in chapter.coursesections.all():
                    if len(temp_section_list) >= 4:
                        return temp_section_list
                    temp_section_list.append({
                        'chapter': chapter.chapter,
                        'name': section.name,
                        'free_trail': section.free_trail,
                    })
            return temp_section_list
    
        class Meta:
            db_table = "luffy_course"
            verbose_name = "课程"
            verbose_name_plural = "课程"
    
        def __str__(self):
            return "%s" % self.name
      
    class CourseCategory(BaseModel):
        """分类"""
        name = models.CharField(max_length=64, unique=True, verbose_name="分类名称")
        orders = models.IntegerField(default=0)
        class Meta:
            db_table = "luffy_course_category"
            verbose_name = "分类"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return "%s" % self.name
        
      
    class CourseChapter(BaseModel):
        """章节"""
        course = models.ForeignKey("Course", related_name='coursechapters', on_delete=models.CASCADE, verbose_name="课程名称")
        chapter = models.SmallIntegerField(verbose_name="第几章", default=1)
        name = models.CharField(max_length=128, verbose_name="章节标题")
        summary = models.TextField(verbose_name="章节介绍", blank=True, null=True)
        pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True)
        orders = models.IntegerField(default=0)
    
        class Meta:
            db_table = "luffy_course_chapter"
            verbose_name = "章节"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return "%s:(第%s章)%s" % (self.course, self.chapter, self.name)
    
    
    class CourseSection(BaseModel):
        """课时"""
        section_type_choices = (
            (0, '文档'),
            (1, '练习'),
            (2, '视频')
        )
        chapter = models.ForeignKey("CourseChapter", related_name='coursesections', on_delete=models.CASCADE,
                                    verbose_name="课程章节")
        name = models.CharField(max_length=128, verbose_name="课时标题")
        orders = models.PositiveSmallIntegerField(verbose_name="课时排序")
        section_type = models.SmallIntegerField(default=2, choices=section_type_choices, verbose_name="课时种类")
        section_link = models.CharField(max_length=255, blank=True, null=True, verbose_name="课时链接",
                                        help_text="若是video,填vid,若是文档,填link")
        duration = models.CharField(verbose_name="视频时长", blank=True, null=True, max_length=32)  # 仅在前端展示使用
        pub_date = models.DateTimeField(verbose_name="发布时间", auto_now_add=True)
        free_trail = models.BooleanField(verbose_name="是否可试看", default=False)
    
    
        class Meta:
            db_table = "luffy_course_Section"
            verbose_name = "课时"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return "%s-%s" % (self.chapter, self.name)
    
    

    adminx.py

    import xadmin
    from . import models
    # 注册xadmin后台管理
    xadmin.site.register(models.Course)
    xadmin.site.register(models.CourseCategory)
    xadmin.site.register(models.CourseChapter)
    xadmin.site.register(models.CourseSection)
    

    urls.py

    from django.urls import path, re_path
    from . import views
    urlpatterns = [
        path('free', views.FreeCourseListAPIView.as_view()),
        re_path('^free/(?P<pk>d+)$', views.FreeCourseRetrieveAPIView.as_view()),
        
        path('category', views.CategoryListAPIView.as_view()),
        path('chapters', views.ChapterListAPIView.as_view()),
    ]
    

    serializers.py

    from rest_framework import serializers
    from .import models
    # 课程序列化
    class FreeCourseModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Course
            fields = (
                      'id',
                      'name',
                      'course_img',
                      'brief',
                      'level_name',
                      'period',
                      'students',
                      'price',
                      )
    # 分类序列化
    class CategoryModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.CourseCategory
            fields = ('name', 'id')
    
    class CourseSectionModelSerialize(serializers.ModelSerializer):
        class Meta:
            model = models.CourseSection
            fields = '__all__'  # 所有字段
    # 章节
    class CourseChapterModelSerializer(serializers.ModelSerializer):
        coursesections = CourseSectionModelSerialize(many=True) # 子序列化
        class Meta:
            model = models.CourseChapter
            fields = (
                'id',
                'name',
                'chapter',
                'summary',
                'coursesections'
            )
    

    views.py

    from rest_framework.generics import ListAPIView
    from . import models, serializers
    
    # 配置过滤器类,导包, 排序过滤器
    from rest_framework.filters import OrderingFilter
    
    # 导包, 搜索过滤器
    from rest_framework.filters import SearchFilter
    
    # 自定义过滤器,导入
    from .filters import LimitFilter
    
    # 分类过滤器
    from django_filters.rest_framework import DjangoFilterBackend
    
    # 导入自定义分页器
    from .paginations import CouerPageNumberPagination
    
    # 自定义分类区间筛选导入
    from.filters import CourseFilterSet
    
    # 群查
    class FreeCourseListAPIView(ListAPIView):
        queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by('-orders').all()
        serializer_class = serializers.FreeCourseModelSerializer
    
    # 群查排序过滤器  1、导包
        # 2、配置过滤器类
        # # LimitFilter 自定义过滤器 访问url格式http://127.0.0.1:8000/course/free?limit=2
        filter_backends = [OrderingFilter, SearchFilter, LimitFilter, DjangoFilterBackend ]
        # 3.添加过滤的字段
        # 访问接口方式为http://127.0.0.1:8000/course/free?ordering=-id,price
        # ordering = 'price'
        ordering_fields = ['price', 'id']
    
    # 群查搜索过滤器
    # 1、 导包
    # 2、 配置过滤器类,统一配置在filter_backends中,如上
    # 3、 添加搜索字段,访问链接格式 http://127.0.0.1:8000/course/free?search=python
        search_fields = ['name', 'brief']
    
    # 自定义过滤器,新建filters.py文件,完成自定义
    # LimitFilter 自定义过滤器 访问url格式http://127.0.0.1:8000/course/free?limit=2
    
    # 分类过滤器
    # 分类筛选过滤器:1、安装环境-- pip install django-filter
    #  2、然后在过滤器库:filter_backends =[]中配置DjangoFilterBackend
    # 3、在filter_fields 中配置分组筛选字段
    #  访问数据格式:http://127.0.0.1:8000/course/free?course_category=2
    # 参与分类筛选的字段:所有字段都可以,但是用于分组的字段更有意义
        filter_fields = ['course_category']
        # 自定义区间分组筛选过滤器,从自定义文件导入
        filter_class = CourseFilterSet
    
    
    # 分页器
    # 新建 paginations.py
    # 1、导入自定义分页器
    # 2、选择分页器, 访问格式:http://127.0.0.1:8000/course/free?page=2
        pagination_class = CouerPageNumberPagination
    
    # 单查
    from rest_framework.generics import RetrieveAPIView
    class FreeCourseRetrieveAPIView(RetrieveAPIView):
        queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by('-orders')
        serializer_class = serializers.FreeCourseModelSerializer
    
    
    # 分类查询 群查
    class CategoryListAPIView(ListAPIView):
        queryset = models.CourseCategory.objects.filter(is_delete=False, is_show=True).order_by('-orders').all()
        serializer_class = serializers.CategoryModelSerializer
    
    
    # 课程章节查询, 群查
    class ChapterListAPIView(ListAPIView):
        queryset = models.CourseChapter.objects.filter(is_delete=False, is_show=True).order_by('-orders').all()
        serializer_class = serializers.CourseChapterModelSerializer
    
    

    自定义过滤器文件入口

    filters.py

    # 自定义过滤器
    from rest_framework.filters import BaseFilterBackend
    # 自定义限制过滤器,限制显示条数
    class LimitFilter(BaseFilterBackend):
        def filter_queryset(self, request, queryset, view):
            # request:从前台请求获取过滤的条件 query_params
    		# queryset:要处理的数据
    		# view:从视图中反射过滤相关的配置
            limit = request.query_params.get('limit')
            try:
                return queryset[:int(limit)]  # queryset数据库查询结果
            except:
                return queryset
    
    
    # 分类筛选,自定义区间筛选        
    # 基于django-filter插件,自定义分类筛选器,完成指定区间筛选(一般都是对应数字字段)
    from django_filters.rest_framework.filterset import FilterSet
    from django_filters import filters
    from . import models
    class CourseFilterSet(FilterSet):
        # 自定义过滤字段及条件
        max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')
        min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
        class Meta:
            model = models.Course
            fields = ['course_category', 'max_price', 'min_price']
    
    

    自定义分页器导入

    paginations.py

    # 分页器
    from rest_framework.pagination import PageNumberPagination
    from rest_framework.pagination import LimitOffsetPagination
    from rest_framework.pagination import CursorPagination
    
    class CouerPageNumberPagination(PageNumberPagination):
        # 默认一页条数
        page_size = 2
        # 访问路径的额外参数(选择哪一页的 key)
        page_query_param = 'page'
        # 用户自定义一页条数
        page_size_query_param = 'page_size'
        # 用户自定义一页最大控制条数
        max_page_size = 10
    
    class CourseLimitOffsetPagination(LimitOffsetPagination):
        # 默认一页条数
        default_limit = 2
    
        limit_query_param = 'limit'
        offset_query_param = 'offset'
        max_limit = 2
    
    class CourseCursorPagination(CursorPagination):
        cursor_query_param = 'cursor'
        page_size = 2
        page_size_query_param = 'page_size'
        max_page_size = 2
    # ordering = 'id'  # 默认排序规则,不能和排序过滤器OrderingFilter共存
    

    补充

    群查接口各种筛选组件数据准备

    models.py

    class Car(models.Model):
        name = models.CharField(max_length=16, unique=True, verbose_name='车名')
        price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='价格')
        brand = models.CharField(max_length=16, verbose_name='品牌')
    
        class Meta:
            db_table = 'api_car'
            verbose_name = '汽车表'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    

    admin.py

    admin.site.register(models.Car)
    
    

    serializers.py

    class CarModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Car
            fields = ['name', 'price', 'brand']
    
    

    urls.py

    url(r'^cars/$', views.CarListAPIView.as_view()),
    
    

    drf搜索过滤组件

    views.py 搜索组件使用方法:路由后缀加 /?search=1 (name和price中包含1的数据都会被查询出来)

    from rest_framework.generics import ListAPIView 
    # 第一步:drf的SearchFilter - 搜索过滤
    from rest_framework.filters import SearchFilter
    
    class CarListAPIView(ListAPIView):
        queryset = models.Car.objects.all() 
        serializer_class = serializers.CarModelSerializer  #自定义认证
    
        # 第二步:局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
        filter_backends = [SearchFilter]
    
        # 第三步:SearchFilter过滤类依赖的过滤条件 => 接口:/cars/?search=...
        search_fields = ['name', 'price']  #筛选字段
        # eg:/cars/?search=1,name和price中包含1的数据都会被查询出
    
    

    drf排序过滤组件

    views.py

    from rest_framework.generics import ListAPIView
    
    # 第一步:drf的OrderingFilter - 排序过滤
    from rest_framework.filters import OrderingFilter
    
    class CarListAPIView(ListAPIView):
        queryset = models.Car.objects.all()
        serializer_class = serializers.CarModelSerializer
    
        # 第二步:局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
        filter_backends = [OrderingFilter]
    
        # 第三步:OrderingFilter过滤类依赖的过滤条件 => 接口:/cars/?ordering=...
        ordering_fields = ['pk', 'price']
        # eg:/cars/?ordering=-price,pk,先按price降序,如果出现price相同,再按pk升序
    
    
    

    drf基础分页组件

    paginations.py

    from rest_framework.pagination import PageNumberPagination
    
    class MyPageNumberPagination(PageNumberPagination):
        # ?page=页码  定义代表页码的属性,如果写pages,就是?pages=页码
        page_query_param = 'page'
        # ?page=页码 设置默认下一页显示的条数
        page_size = 3
        # ?page=页码&page_size=条数 用户自定义一页显示的条数
        page_size_query_param = 'page_size'
        # 用户自定义一页显示的条数最大限制:数值超过5也只显示5条
        max_page_size = 5
    
    

    views.py

    from rest_framework.generics import ListAPIView
    
    class CarListAPIView(ListAPIView):
        # 如果queryset没有过滤条件,就必须 .all(),不然分页会出问题
        queryset = models.Car.objects.all()
        serializer_class = serializers.CarModelSerializer
        
        # 分页组件 - 给视图类配置分页类即可 - 分页类需要自定义,继承drf提供的分页类即可
        pagination_class = pagenations.MyPageNumberPagination
    
      #eg:/cars/  显示第一页三条
        /cars/?page=2&page_size=4   每页显示4条,显示第二页的4条
    
    
  • 相关阅读:
    风险分解结构
    WBS 工作分解结构
    react函数式组件(非路由组件)实现路由跳转
    react使用antd组件递归实现左侧菜单导航树
    React4.0以上如何获取当前的路由地址呢
    浅谈react传入路由参数---withRouter组件
    react项目实现维持登录与自动登录
    async和await应用步骤分析+优化异常处理
    跨域场景&&跨域处理方案
    vscode react中标签自动补全 vscode jsx语法自动补全html标签
  • 原文地址:https://www.cnblogs.com/chmily/p/12055011.html
Copyright © 2011-2022 走看看