CodeRoadMap
路线图学习路径文章题库资源社区

浏览

首页路线图学习路径知识库题库文章资源社区我的学习
CodeRoadMap

中文编程学习导航:路线图、讲义与题库,进度可同步。

路线图学习路径文章题库社区

© 2026 CodeRoadMap

津ICP备2026012044号-1|coderoadmap@126.com
首页/Python 100 天/55.RESTful架构和DRF进阶

课程目录

  1. 0101.初识Python
  2. 0202.第一个Python程序
  3. 0303.Python语言中的变量
  4. 0404.Python语言中的运算符
  5. 0505.分支结构
  6. 0606.循环结构
  7. 0707.分支和循环结构实战
  8. 0808.常用数据结构之列表-1
  9. 0909.常用数据结构之列表-2
  10. 1010.常用数据结构之元组
  11. 1111.常用数据结构之字符串
  12. 1212.常用数据结构之集合
  13. 1313.常用数据结构之字典
  14. 1414.函数和模块
  15. 1515.函数应用实战
  16. 1616.函数使用进阶
  17. 1717.函数高级应用
  18. 1818.面向对象编程入门
  19. 1919.面向对象编程进阶
  20. 2020.面向对象编程应用
  21. 2121.文件读写和异常处理
  22. 2222.对象的序列化和反序列化
  23. 2323.Python读写CSV文件
  24. 2424.Python读写Excel文件-1
  25. 2525.Python读写Excel文件-2
  26. 2626.Python操作Word和PowerPoint文件
  27. 2727.Python操作PDF文件
  28. 2828.Python处理图像
  29. 2929.Python发送邮件和短信
  30. 3030.正则表达式的应用
  31. 3131.Python语言进阶
  32. 3232-33.Web前端入门
  33. 3334-35.玩转Linux操作系统
  34. 3436.关系型数据库和MySQL概述
  35. 3537.SQL详解之DDL
  36. 3638.SQL详解之DML
  37. 3739.SQL详解之DQL
  38. 3840.SQL详解之DCL
  39. 3941.MySQL新特性
  40. 4042.视图、函数和过程
  41. 4143.索引
  42. 4244.Python接入MySQL数据库
  43. 4345.Hive实战
  44. 4446.Django快速上手
  45. 4547.深入模型
  46. 4648.静态资源和Ajax请求
  47. 4749.Cookie和Session
  48. 4850.制作报表
  49. 4951.日志和调试工具栏
  50. 5052.中间件的应用
  51. 5153.前后端分离开发入门
  52. 5254.RESTful架构和DRF入门
  53. 5355.RESTful架构和DRF进阶
  54. 5456.使用缓存
  55. 5557.接入三方平台
  56. 5658.异步任务和定时任务
  57. 5759.单元测试
  58. 5860.项目上线
  59. 5961.网络数据采集概述
  60. 6062.用Python获取网络资源-1
  61. 6162.用Python解析HTML页面-2
  62. 6263.并发编程在爬虫中的应用
  63. 6363.Python中的并发编程-1
  64. 6463.Python中的并发编程-2
  65. 6563.Python中的并发编程-3
  66. 6664.使用Selenium抓取网页动态内容
  67. 6765.爬虫框架Scrapy简介
  68. 6866.数据分析概述
  69. 6967.环境准备
  70. 7068.NumPy的应用-1
  71. 7169.NumPy的应用-2
  72. 7270.NumPy的应用-3
  73. 7371.NumPy的应用-4
  74. 7472.深入浅出pandas-1
  75. 7573.深入浅出pandas-2
  76. 7674.深入浅出pandas-3
  77. 7775.深入浅出pandas-4
  78. 7876.深入浅出pandas-5
  79. 7977.深入浅出pandas-6
  80. 8078.数据可视化-1
  81. 8179.数据可视化-2
  82. 8280.数据可视化-3
  83. 8381.浅谈机器学习
  84. 8482.k最近邻算法
  85. 8583.决策树和随机森林
  86. 8684.朴素贝叶斯算法
  87. 8785.回归模型
  88. 8886.K-Means聚类算法
  89. 8987.集成学习算法
  90. 9088.神经网络模型
  91. 9189.自然语言处理入门
  92. 9290.机器学习实战
  93. 9391.团队项目开发的问题和解决方案
  94. 9492.Docker容器技术详解
  95. 9593.MySQL性能优化
  96. 9694.网络API接口设计
  97. 9795.使用Django开发商业项目
  98. 9896.软件测试和自动化测试
  99. 9997.电商网站技术要点剖析
  100. 10098.项目部署上线和性能调优
  101. 10199.面试中的公共问题
  102. 102100.补充内容
第 53 课1 天

55.RESTful架构和DRF进阶

除了上一节讲到的方法,使用DRF创建REST风格的数据接口也可以通过CBV(基于类的视图)的方式。使用CBV创建数据接口的特点是代码简单,开发效率高,但是没有F

课程内容

RESTful架构和DRF进阶

除了上一节讲到的方法,使用DRF创建REST风格的数据接口也可以通过CBV(基于类的视图)的方式。使用CBV创建数据接口的特点是代码简单,开发效率高,但是没有FBV(基于函数的视图)灵活,因为使用FBV的方式,数据接口对应的视图函数执行什么样的代码以及返回什么的数据是高度可定制的。下面我们以定制学科的数据接口为例,讲解通过CBV方式定制数据接口的具体做法。

使用CBV

继承APIView的子类

修改之前项目中的polls/views.py,去掉show_subjects视图函数,添加一个名为SubjectView的类,该类继承自ListAPIView,ListAPIView能接收GET请求,它封装了获取数据列表并返回JSON数据的get方法。ListAPIView是APIView 的子类,APIView还有很多的子类,例如CreateAPIView可以支持POST请求,UpdateAPIView可以支持PUT和PATCH请求,DestoryAPIView可以支持DELETE请求。SubjectView 的代码如下所示。

from rest_framework.generics import ListAPIView


class SubjectView(ListAPIView):
    # 通过queryset指定如何获取学科数据
    queryset = Subject.objects.all()
    # 通过serializer_class指定如何序列化学科数据
    serializer_class = SubjectSerializer

刚才说过,由于SubjectView的父类ListAPIView已经实现了get方法来处理获取学科列表的GET请求,所以我们只需要声明如何获取学科数据以及如何序列化学科数据,前者用queryset属性指定,后者用serializer_class属性指定。要使用上面的SubjectView,需要修改urls.py文件,如下所示。

urlpatterns = [
    path('api/subjects/', SubjectView.as_view()),   
]

很显然,上面的做法较之之前讲到的FBV要简单很多。

继承ModelViewSet

如果学科对应的数据接口需要支持GET、POST、PUT、PATCH、DELETE请求来支持对学科资源的获取、新增、更新、删除操作,更为简单的做法是继承ModelViewSet来编写学科视图类。再次修改polls/views.py文件,去掉类,添加一个名为的类,代码如下所示。

SubjectView
SubjectViewSet
from rest_framework.viewsets import ModelViewSet


class SubjectViewSet(ModelViewSet):
    queryset = Subject.objects.all()
    serializer_class = SubjectSerializer

通过查看ModelViewSet类的源代码可以发现,该类共有6个父类,其中前5个父类分别实现对POST(新增学科)、GET(获取指定学科)、PUT/PATCH(更新学科)、DELETE(删除学科)和GET(获取学科列表)操作的支持,对应的方法分别是create、retrieve、update、destroy和list。由于ModelViewSet的父类中已经实现了这些方法,所以我们几乎没有编写任何代码就完成了学科数据全套接口的开发,我们要做的仅仅是指出如何获取到数据(通过queryset属性指定)以及如何序列化数据(通过serializer_class属性指定),这一点跟上面继承APIView的子类做法是一致的。

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass

要使用上面的SubjectViewSet,需要在urls.py文件中进行URL映射。由于ModelViewSet相当于是多个视图函数的汇总,所以不同于之前映射URL的方式,我们需要先创建一个路由器并通过它注册SubjectViewSet,然后将注册成功后生成的URL一并添加到urlspattern列表中,代码如下所示。

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('api/subjects', SubjectViewSet)
urlpatterns += router.urls

除了ModelViewSet类外,DRF还提供了一个名为ReadOnlyModelViewSet 的类,从名字上就可以看出,该类是只读视图的集合,也就意味着,继承该类定制的数据接口只能支持GET请求,也就是获取单个资源和资源列表的请求。

数据分页

在使用GET请求获取资源列表时,我们通常不会一次性的加载所有的数据,除非数据量真的很小。大多数获取资源列表的操作都支持数据分页展示,也就说我们可以通过指定页码(或类似于页码的标识)和页面大小(一次加载多少条数据)来获取不同的数据。我们可以通过对QuerySet对象的切片操作来实现分页,也可以利用Django框架封装的Paginator和Page对象来实现分页。使用DRF时,可以在Django配置文件中修改REST_FRAMEWORK并配置默认的分页类和页面大小来实现分页,如下所示。

REST_FRAMEWORK = {
    'PAGE_SIZE': 10,
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination'
}

除了上面配置的PageNumberPagination分页器之外,DRF还提供了LimitOffsetPagination和CursorPagination分页器,值得一提的是CursorPagination,它可以避免使用页码分页时暴露网站的数据体量,有兴趣的读者可以自行了解。如果不希望使用配置文件中默认的分页设定,可以在视图类中添加一个pagination_class属性来重新指定分页器,通常可以将该属性指定为自定义的分页器,如下所示。

from rest_framework.pagination import PageNumberPagination


class CustomizedPagination(PageNumberPagination):
    # 默认页面大小
    page_size = 5
    # 页面大小对应的查询参数
    page_size_query_param = 'size'
    # 页面大小的最大值
    max_page_size = 50
class SubjectView(ListAPIView):
    # 指定如何获取数据
    queryset = Subject.objects.all()
    # 指定如何序列化数据
    serializer_class = SubjectSerializer
    # 指定如何分页
    pagination_class = CustomizedPagination

如果不希望数据分页,可以将pagination_class属性设置为None来取消默认的分页器。

数据筛选

如果希望使用CBV定制获取老师信息的数据接口,也可以通过继承ListAPIView来实现。但是因为要通过指定的学科来获取对应的老师信息,因此需要对老师数据进行筛选而不是直接获取所有老师的数据。如果想从请求中获取学科编号并通过学科编号对老师进行筛选,可以通过重写get_queryset方法来做到,代码如下所示。

class TeacherView(ListAPIView):
    serializer_class = TeacherSerializer

    def get_queryset(self):
        queryset = Teacher.objects.defer('subject')
        try:
            sno = self.request.GET.get('sno', '')
            queryset = queryset.filter(subject__no=sno)
            return queryset
        except ValueError:
            raise Http404('No teachers found.')

除了上述方式之外,还可以使用三方库django-filter来配合DRF实现对数据的筛选,使用django-filter后,可以通过为视图类配置filter-backends属性并指定使用DjangoFilterBackend来支持数据筛选。在完成上述配置后,可以使用filter_fields 属性或filterset_class属性来指定如何筛选数据,有兴趣的读者可以自行研究。

← 上一课54.RESTful架构和DRF入门下一课 →56.使用缓存