Justin-刘清政的博客

python/路飞项目/6-课程模块/5-课程主页之课程接口

2020-03-06

路由:course/urls.py
1
2
router.register('categories', views.CourseCategoryViewSet, 'categories')  # 分类
router.register('free', views.CourseViewSet, 'free') # 课程
视图:course/views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from . import models, serializers
# 课程分类群查
class CourseCategoryViewSet(GenericViewSet, ListModelMixin):
queryset = models.CourseCategory.objects.filter(is_delete=False, is_show=True).all()
serializer_class = serializers.CourseCategorySerializer

# 课程群查

# 分页组件:基础分页(采用)、偏移分页、游标分页(了解)
from . import pagination

# 过滤组件:搜索功能、排序功能
from rest_framework.filters import SearchFilter, OrderingFilter

# django-filter插件:分类功能
from django_filters.rest_framework import DjangoFilterBackend
from .filters import CourseFilterSet

# 前台携带所有过滤规则的请求url:
# http://127.0.0.1:8000/course/free/?page=1&page_size=10&search=python&ordering=-price&min_price=30&count=1
class CourseViewSet(GenericViewSet, ListModelMixin):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).all()
serializer_class = serializers.CourseSerializer

# 分页组件
pagination_class = pagination.PageNumberPagination

# 过滤组件:实际开发,有多个过滤条件时,要把优先级高的放在前面
filter_backends = [SearchFilter, OrderingFilter, DjangoFilterBackend]

# 参与搜索的字段
search_fields = ['name', 'id', 'brief']

# 允许排序的字段
ordering_fields = ['id', 'price', 'students']

# 过滤类:分类过滤、区间过滤
filter_class = CourseFilterSet
分类区间过滤:filters.py
1
2
3
4
5
6
7
8
9
10
11
12
13
# django-filter插件 过滤类
from django_filters.filterset import FilterSet
from . import models
from django_filters import filters
class CourseFilterSet(FilterSet):
# 区间过滤:field_name关联的Model字段;lookup_expr设置规则;gt是大于,gte是大于等于;
min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')
class Meta:
model = models.Course
# 如果过滤条件仅仅就是Model已有的字段,方式一更好
# 但是方式二可以自定义过滤字段
fields = ['course_category', 'min_price', 'max_price']
分页:paginations.py
1
2
3
4
5
6
7
8
9
10
11
from rest_framework.pagination import PageNumberPagination as DrfPageNumberPagination

class PageNumberPagination(DrfPageNumberPagination):
# 默认一页显示的条数
page_size = 2
# url中携带页码的key
page_query_param = 'page'
# url中用户携带自定义一页条数的key
page_size_query_param = 'page_size'
# 用户最大可自定义一页的条数
max_page_size = 10
模型:course/models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Course(BaseModel):
# ...

@property
def course_type_name(self):
return self.get_course_type_display()

@property
def level_name(self):
return self.get_level_display()

@property
def status_name(self):
return self.get_status_display()


# 连表序列化字段
@property
def section_list(self):
# 检索所以章节所以课时,返回前4课时,不足4课时全部返回
temp_section_list = []

for chapter in self.coursechapters.all():
for section in chapter.coursesections.all():
temp_section_list.append({
'name': section.name,
'section_link': section.section_link,
'duration': section.duration,
'free_trail': section.free_trail,
})
if len(temp_section_list) >= 4:
return temp_section_list # 最多4条

return temp_section_list # 不足4条


class Teacher(BaseModel):
# ...
@property
def role_name(self):
return self.get_role_display()
序列化:course/serializers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from rest_framework import serializers
from . import models
class CourseCategorySerializer(serializers.ModelSerializer):
class Meta:
model = models.CourseCategory
fields = ('id', 'name')


# 子序列化
class TeacherSerializer(serializers.ModelSerializer):
class Meta:
model = models.Teacher
fields = ('name', 'role_name', 'title', 'signature', 'image', 'brief')


class CourseSerializer(serializers.ModelSerializer):
teacher = TeacherSerializer(many=False)

class Meta:
model = models.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',
)
补充
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""
GenericAPIView:额外的两个属性两个方法
filter_backends:配置过滤类们
filter_queryset():调用配置的过滤类完成过滤(都是在群查接口中完成,传入queryset,接收过滤后的queryset)
# 源码使用
queryset = self.filter_queryset(self.get_queryset())

pagination_class:配置分页类
paginate_queryset():调用配置的分页类完成分页(都是在群查接口中完成,传入queryset,接收分页滤后的分页对象)
# 源码使用
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
"""


"""
搜索组件
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的所有结果
"""

"""
排序组件
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降序
"""

"""
django-filter插件:分类功能
前提:安装django-filter插件
>: pip install django-filter

方式一
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下的所有课程
"""

"""
区间过滤

1)自定义过滤类继承django-filter插件的FilterSet类,绑定Model表,并设置自定义区间规则字段
from django_filters.filterset import FilterSet
from . import models
class CourseFilterSet(FilterSet):
# 区间过滤:field_name关联的Model字段;lookup_expr设置规则;gt是大于,gte是大于等于;
min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')
class Meta:
model = models.Course
fields = ['min_price', 'max_price']

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_price=30&max_price=60 # 拿课程价格在30~60的所有课程
"""
使用支付宝打赏
使用微信打赏

点击上方按钮,请我喝杯咖啡!

扫描二维码,分享此文章