zoukankan      html  css  js  c++  java
  • 28-课程主页之课程接口

    课程主页之课程接口

    一、课程分类接口

    1. course/views.py

    from rest_framework.viewsets import GenericViewSet
    from rest_framework.mixins import ListModelMixin
    
    from . import serializer
    from . import models
    
    
    # 查询所有课程分类接口
    class CourseCategoryView(GenericViewSet, ListModelMixin):
    	queryset = models.CourseCategory.objects.filter(is_delete=False, is_show=True).order_by('orders').all()
    	serializer_class = serializer.CourseCategorySerializer
    

    2. course/serializer.py

    from rest_framework import serializers
    from . import models
    
    
    # 课程分类序列化器
    class CourseCategorySerializer(serializers.ModelSerializer):
    	class Meta:
    		model = models.CourseCategory
    		fields = ['id', 'name', ]
    

    3. course/urls.py

    from django.urls import path, include
    from . import views
    
    from rest_framework.routers import SimpleRouter
    
    router = SimpleRouter()
    
    router.register('categories', views.CourseCategoryView, 'categories')
    
    urlpatterns = [
    	path('', include(router.urls)),
    ]
    

    4. apps/urls.py

    path('course/', include('course.urls')),
    

    5. 流程

    1. 视图定义课程分类视图, 继承GenericViewSet, ListModelMixin
    2. 对课程分类接口进行is_delete, is_show过滤, 再使用orders进行排序
    3. 序列化定义课程分类序列化类. 不过需要给课程分类的id, 在分类的时候, 需要前端传递过来实现分类. 然后只需要给课程分类名即可.
    4. 配置course中的路由, 配置总路由
    

    二、课程接口

    1. views.py

    # 查询所有课程详情接口
    from .paginations import PageNumberPagination
    from rest_framework.filters import OrderingFilter, SearchFilter
    
    from django_filters.rest_framework import DjangoFilterBackend
    # 自定义的过滤规则
    from .filters import Myfilter
    # 区间过滤
    from .filters import CourseFilterSet
    
    
    # 单查、群查课程接口
    class CourseView(GenericViewSet, ListModelMixin, RetrieveModelMixin):
    	queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by('orders').all()
    	serializer_class = serializer.CourseSerializer
    	# 分页
    	pagination_class = PageNumberPagination
    	''' 原始版本的过滤+排序 '''
    	# 排序
    	# filter_backends = (OrderingFilter, DjangoFilterBackend, SearchFilter)
    	filter_backends = (OrderingFilter, DjangoFilterBackend)
    	ordering_fields = ['id', 'price', 'students']
    	'''
    	过滤+排序分析:
    		1.先走执行ListModelMixin中的List方法
    		2.List方法中回执行self.filter_queryset方法,但是ListModelMixin中没有filter_queryset方法
    		3.从GenericViewSet类中找filter_queryset方法,也没有
    		4.GenericViewSet类继承了ViewSetMixin, generics.GenericAPIView,ViewSetMixin中也没有,在generics.GenericAPIView类中找到了filter_queryset方法
    		5.generics.GenericAPIView中的filter_queryset代码如下
    			        for backend in list(self.filter_backends): 遍历CourseView中的filter_backends
    			            queryset = backend().filter_queryset(self.request, queryset, self) :实例化filter_backends列表中的类的,并执行filter_queryset方法
    				        return queryset:返回queryset对象
    	'''
    	# 过滤(django内置的过滤)
    	# search_field = ['id']
    
    	# 过滤(django-filter提供的过滤,比内置的更加强大,可以过滤外键字段)
    	filter_fields = ['course_category', ]
    	'''
    	排序:
    		使用:http://www127.0.0.1:8000/course/free/?ordering=-id
    		按照id正序倒序排序
    		配置类:
    			filter_backends = (OrderingFilter,)
    		配置字段:
    			ordering_fields = ['id',]
    	内置过滤:
    		使用:http://www127.0.0.1:8000/course/free/?search=39.00
    		按照price过滤(过滤表中自有的字段直接过滤)
    		配置类:
    			filter_backends = (SearchFilter,)
    		配置字段:
    			search_field = ['price']
    	扩展过滤(django-filter)
    		使用:http://www127.0.0.1:8000/course/free/?course_category=1
    		按照course_category过滤(无论是过滤表中自有的字段还是外键字段)
    		配置类:
    			filter_backends = (DjangoFilterBackend)
    		配置字段:
    			filter_fields = ['course_category', ]
    	'''
    	''' django-filter版本的过滤 '''
    	# filter_backends = (DjangoFilterBackend,)
    	# filter_class = CourseFilterSet
    

    2. serializer.py

    class TeacherModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = Teacher
            fields = ('name', 'role_name', 'title', 'signature', 'image', 'brief')
    
    
    class CourseModelSerializer(serializers.ModelSerializer):
        # teacher子序列化
        teacher = TeacherModelSerializer()
    
        class Meta:
            model = Course
            fields = (
                'id',
                'name',
                'course_img',
                'brief',
                'attachment_path',
                'pub_sections',
                'price',
                'students',
                'period',
                'sections',
                'course_type_name',
                'level_name',
                'status_name',
                'teacher',
                'section_list',
            )
    

    3. models.py

    class Course(BaseModel):
        ... 
        @property
        def level_name(self):
            return self.get_level_display()
    
        @property
        def course_type_name(self):
            return self.get_course_type_display()
    
        @property
        def status_name(self):
            return self.get_status_display()
    
        @property
        def section_list(self):
            course_chapter_queryset = self.coursechapters.all()
            course_section_list = []
            for course_chapter in course_chapter_queryset:
                course_section_queryset = course_chapter.coursesections.all()
                for course_section in course_section_queryset:
                    course_section_list.append({
                        'name': course_section.name,
                        'section_type': course_section.section_type,
                        'section_link': course_section.section_link,
                        'duration': course_section.duration,
                    })
                    if len(course_section_list) == 4:
                        return course_section_list
            return course_section_list
        
        
    class Teacher(BaseModel):
        ...
        @property
        def role_name(self):
            return self.get_role_display()    
    

    4. pagination.py

    from rest_framework.pagination import PageNumberPagination as DRFPageNumberPagination
    
    
    class PageNumberPagination(DRFPageNumberPagination):
    	page_size = 1
    	page_query_param = 'page'
    	page_size_query_param = 'page_size'
    	max_page_size = 10
    

    5. filters.py自定义过滤类

    from rest_framework.filters import BaseFilterBackend
    
    
    class CustomFilter(BaseFilterBackend):
        def filter_queryset(self, request, queryset, view):
            # 老师的模糊匹配
            name = request.GET.get('teacher')
            if not name:
                return queryset
            teacher_queryset = queryset.filter(teacher__name__contains=name)
            return teacher_queryset
    

    6. urls.py

    router.register('free', views.CourseView, 'free')
    

    7. 流程

    1. 视图中定义课程视图类继承GenericViewSet,ListModelMixin
    2. 视图中queryset的查询过滤is_delete, is_show, 再使用orders字段进行排序
    3. 序列化中定义课程序列化类, 控制序列化的字段, 在序列化类中针对teacher使用子序列化进行控制teacher包含字段对应数值的展示
    4. 对应choices字段的展示, 有2种方式进行控制, 在序列化类中重写字段, 使用serializerMethod, 模型类中使用@property装饰返回对应get_字段_display()字段参数对应的值.
    5. 配置路由
    6. 配置分页器. 自定义分页器, 使用了as的特殊用法
    

    三、排序和过滤组件

    1. 内置排序组件OrderingFIlter

    # 1)在视图文件views.py中导入drf的搜索组件
    from rest_framework.filters import OrderingFilter
    
    # 2)将搜索组件配置给群查接口视图类的filter_backends
    filter_backends = [OrderingFilter]
    
    # 3)配置视图类关联的Model表允许排序的字段
    ordering_fields = ['id', 'price']
    
    # 4)前台访问该群查接口,采用拼接参数方式用search关键字将搜索目标提供给后台
    http://127.0.0.1:8000/course/free/?ordering=price,-id  # 按price升序,如果price相同,再按id降序
    

    2. 过滤组件

    <1>. 内置过滤组件SearchFIlter
    # 缺点: 外键字段的搜索操作将会抛出异常: Related Field got invalid lookup: icontains
    
    # 1)在视图文件views.py中导入drf的搜索组件
    from rest_framework.filters import SearchFilter
    
    # 2)将搜索组件配置给群查接口视图类的filter_backends
    filter_backends = [SearchFilter]
    
    # 3)配置视图类关联的Model表参与搜索的字段
    search_fields = ['name', 'id']
    
    # 4)前台访问该群查接口,采用拼接参数方式用search关键字将搜索目标提供给后台
    http://127.0.0.1:8000/course/free/?search=2  # id或name中包含2的所有结果
    
    <2>. 第三方过滤组件django-filter
    # 介绍: 争对django内置搜索组件的拓展, 在django内置的基础之上还拓展了外键字段的过滤功能.
    # 前提:安装django-filter插件
    pip install django-filter  (注意: 不要安装成了django-filters)
    
    """方式一"""
    # 1)在视图文件views.py中导入django-filter的功能组件
    from django_filters.rest_framework import DjangoFilterBackend
    
    # 2)将搜索组件配置给群查接口视图类的filter_backends
    filter_backends = [DjangoFilterBackend]
    
    # 3)配置视图类关联的Model表可以分类的字段(通常是可以分组的字段)
    filter_fields = ['course_category']
    
    # 4)前台访问该群查接口,采用拼接参数方式用分类course_category字段将分类条件提供给后台
    http://127.0.0.1:8000/course/free/?course_category=1  # 拿课程分类1下的所有课程
    
    '''方式二'''
    # 1)自定义过滤类继承django-filter插件的FilterSet类,绑定Model表,并设置分类字段
    from django_filters.filterset import FilterSet
    from . import models
    class CourseFilterSet(FilterSet):
        class Meta:
            model = models.Course
            fields = ['course_category']
    
    # 2)在视图文件views.py中导入django-filter的功能组件及自定义的过滤类
    from django_filters.rest_framework import DjangoFilterBackend
    from .filters import CourseFilterSet
            
    # 3)将搜索组件配置给群查接口视图类的filter_backends
    filter_backends = [DjangoFilterBackend]
    
    # 4)配置视图类关联的自定义过滤类
    filter_class = CourseFilterSet
    
    # 5)前台访问该群查接口,采用拼接参数方式用分类course_category字段将分类条件提供给后台
    http://127.0.0.1:8000/course/free/?course_category=1  # 拿课程分类1下的所有课程
    
    <3>. django-filter实现区间过滤
    # 1)自定义过滤类继承django-filter插件的FilterSet类,绑定Model表,并设置自定义区间规则字段
    from django_filters.filterset import FilterSet
    from . import models
    class CourseFilterSet(FilterSet):
        # 区间过滤: students学生中总人数要大于等于min_students, 要小于等于max_students. [min_students, max_students]
        max_students = filters.NumberFilter(field_name='students', lookup_expr='lte')
        min_students = filters.NumberFilter(field_name='students', lookup_expr='gte')
    
        class Meta:
            model = Course
            fields = ['course_category', 'students', 'min_students', 'max_students']
    
    # 2)在视图文件views.py中导入django-filter的功能组件及自定义的过滤类
    from django_filters.rest_framework import DjangoFilterBackend
    from .filters import CourseFilterSet
            
    # 3)将搜索组件配置给群查接口视图类的filter_backends
    filter_backends = [DjangoFilterBackend]
    
    # 4)配置视图类关联的自定义过滤类
    filter_class = CourseFilterSet
    
    # 5)前台访问该群查接口,采用拼接参数方式用自定义区间规则字段将区间条件提供给后台
    http://127.0.0.1:8000/course/free/?min_students=230&max_students=250  # 获取学生总人数230~250之间的数据        
    
    '''
    # django-filter区间过滤源码流程
    	关键: filter_queryset 
    	get_filterset_class: 
    		反射filter_class
    			MetaBase
    			AutoFilterSet 
    			filterset就是我们自定义类实例化出来的对象
    				有值调用: filterset.is_valid()
    				reutrn filterset.qs qs在BaseFilterSet中
    				return self.qs = qs queryset对象
    		反射filter_fields
    '''
    
    <4>. 自定义过滤
    # filters.py
    from rest_framework.filters import BaseFilterBackend
    
    
    class CustomFilter(BaseFilterBackend):
        def filter_queryset(self, request, queryset, view):
            # 老师的模糊匹配
            name = request.GET.get('teacher')
            if not name:
                return queryset
            teacher_queryset = queryset.filter(teacher__name__contains=name)
            return teacher_queryset
        	# 此时返回的queryset就是过滤好的数据
        
    # views.py
    # 自定义过滤: 通过老师名进行模糊匹配
    filter_backends = [CustomFilter]
    

    四、总结

    # 过滤, 排序, 分页的使用范围
    视图类继承关系中必须含有的视图类: ListModelMixin, GenericAPIView
    ListModelMixin中实现的是调用GenericAPIView中对应的过滤,排序(filter_queryset), 分页(paginate_queryset)方法
    GenericAPIView中实现的是循环调用视图类中配置的类, 调用视图类中对应的方法
        def filter_queryset(self, queryset):
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset
    
  • 相关阅读:
    software系列:Tableau10.5安装教程(破解版)
    技巧系列:Excel打印技巧
    Android 3.0 访问WebService 出现 android.os.NetworkOnMainThreadException异常
    Android各种布局
    服务器访问本地磁盘
    Android手机客户端访问.NET服务器端的方法(1)
    flex webservice
    android学习之 intent 实例
    Android手机客户端访问.NET服务器端的方法(2)
    一篇不错的讲解Java异常的文章(转载)感觉很不错,读了以后很有启发
  • 原文地址:https://www.cnblogs.com/borntodie/p/14431284.html
Copyright © 2011-2022 走看看