文档教程【免费下载链接】Python-100-DaysPython - 100天从新手到大师项目地址https://gitcode.com/GitHub_Trending/py/Python-100-Days点击查看免费下载本篇是 Python-100-Days 教程第 55 天Day46-60/55.RESTful架构和DRF进阶.md的实战进阶指南讲解在 Django 项目中用 DRFDjango REST Framework的 CBV基于类的视图取代 FBV 来构建 REST 风格数据接口。读完本篇你将掌握如何通过继承ListAPIView快速实现 GET 接口、如何用ModelViewSet一行代码集齐增删改查全套接口、如何通过路由器注册 ViewSet 完成 URL 映射以及如何配置全局/自定义分页器并用django-filter对资源列表做灵活筛选。1. 为什么从 FBV 走向 CBV回顾与对比在第 54 天的入门教程Day46-60/54.RESTful架构和DRF入门.md中我们使用 FBV基于函数的视图配合api_view装饰器编写数据接口from rest_framework.decorators import api_view from rest_framework.response import Response api_view((GET, )) def show_subjects(request: HttpRequest) - HttpResponse: subjects Subject.objects.all().order_by(no) # 创建序列化器对象并指定要序列化的模型 serializer SubjectSerializer(subjects, manyTrue) # 通过序列化器的data属性获得模型对应的字典并通过创建Response对象返回JSON格式的数据 return Response(serializer.data)FBV 的优势是高度可定制视图函数执行什么代码、返回什么数据都由开发者自由控制。缺点是每次新增一个接口都要手写请求方法检查、数据获取、序列化、响应组装等样板代码。而 CBV 将“接收请求 → 取数据 → 序列化 → 返回 JSON”这条链路封装在基类中开发者只需声明“数据从哪里来”和“数据如何序列化”。这就是本篇文章要介绍的核心方法。第 54 天还介绍了配套的序列化器Day46-60/54.RESTful架构和DRF入门.md包括SubjectSerializer、SubjectSimpleSerializer和TeacherSerializer本文的 CBV 示例会直接复用这些序列化器。2. 使用 CBV继承APIView的子类2.1 继承ListAPIView实现 GET 列表接口DRF 提供了一套基于通用类的视图GenericAPIView 体系。修改投票项目中的polls/views.py去掉show_subjects视图函数添加一个继承自ListAPIView的SubjectView类from rest_framework.generics import ListAPIView class SubjectView(ListAPIView): # 通过queryset指定如何获取学科数据 queryset Subject.objects.all() # 通过serializer_class指定如何序列化学科数据 serializer_class SubjectSerializer关键点说明ListAPIView能接收 GET 请求内部封装了获取数据列表并返回 JSON 数据的get方法由于get方法已被父类实现我们只需要声明两件事用queryset属性指定如何获取数据用serializer_class属性指定如何序列化数据。ListAPIView是APIView的子类。APIView体系下还有大量现成的子类覆盖了 CRUD 的各种组合通用视图类支持的请求方法封装的核心操作CreateAPIViewPOST新建资源ListAPIViewGET获取资源列表RetrieveAPIViewGET获取单个资源UpdateAPIViewPUT / PATCH更新资源DestroyAPIViewDELETE删除资源ListCreateAPIViewGET / POST列表 新建RetrieveUpdateDestroyAPIViewGET / PUT / PATCH / DELETE单资源全操作2.2 修改 URL 映射使用上面的SubjectView需要修改urls.pyurlpatterns [ path(api/subjects/, SubjectView.as_view()), ]这里的as_view()是 Django 基于类的视图的标准入口DRF 的通用视图同样遵循这一约定。相比 FBV 的做法Day46-60/54.RESTful架构和DRF入门.md 中的path(api/teachers/, show_teachers)CBV 只是把视图函数换成了SubjectView.as_view()代码量却减少了一大截。2.3APIView的策略属性与默认配置APIView是 DRF 所有视图类的根基。从源码结构看参见 Day91-100/95.使用Django开发商业项目.md 中对APIView的代码展示它把渲染器、解析器、认证、限流、权限等策略全部抽象为可覆盖的类属性class APIView(View): # The following policies may be set at either globally, or per-view. renderer_classes api_settings.DEFAULT_RENDERER_CLASSES parser_classes api_settings.DEFAULT_PARSER_CLASSES authentication_classes api_settings.DEFAULT_AUTHENTICATION_CLASSES throttle_classes api_settings.DEFAULT_THROTTLE_CLASSES permission_classes api_settings.DEFAULT_PERMISSION_CLASSES content_negotiation_class api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS metadata_class api_settings.DEFAULT_METADATA_CLASS versioning_class api_settings.DEFAULT_VERSIONING_CLASSDRF 的默认策略集中在REST_FRAMEWORK配置字典中常用的默认项包括REST_FRAMEWORK { DEFAULT_RENDERER_CLASSES: ( rest_framework.renderers.JSONRenderer, rest_framework.renderers.BrowsableAPIRenderer, ), DEFAULT_PARSER_CLASSES: ( rest_framework.parsers.JSONParser, rest_framework.parsers.FormParser, rest_framework.parsers.MultiPartParser ), DEFAULT_AUTHENTICATION_CLASSES: ( rest_framework.authentication.SessionAuthentication, rest_framework.authentication.BasicAuthentication ), DEFAULT_PERMISSION_CLASSES: ( rest_framework.permissions.AllowAny, ), DEFAULT_THROTTLE_CLASSES: (), }在具体视图类中覆盖同名属性即可定制某个接口的行为例如class EstateViewSet(CacheResponseMixin, ModelViewSet): # 通过queryset指定如何获取数据资源 queryset Estate.objects.all().select_related(district).prefetch_related(agents) # 通过serializer_class指定如何序列化数据 serializer_class EstateSerializer # 指定根据哪些字段进行数据筛选 filter_fields (district, name) # 指定根据哪些字段对数据进行排序 ordering_fields (hot, ) # 指定用于进行用户身份验证的类 authentication_classes (MyAuthentication, )以上片段引自 Day91-100/95.使用Django开发商业项目.md展示了同一个 CBV 同时覆盖分页、筛选、排序和认证策略的实际用法。3. 使用 CBV继承ModelViewSet一键集齐 CRUD3.1 极简的SubjectViewSet如果学科数据接口需要支持 GET、POST、PUT、PATCH、DELETE 请求完成对学科资源的获取、新增、更新、删除全套操作更简单的做法是继承ModelViewSet。再次修改polls/views.py去掉SubjectView类添加SubjectViewSetfrom rest_framework.viewsets import ModelViewSet class SubjectViewSet(ModelViewSet): queryset Subject.objects.all() serializer_class SubjectSerializer从源码结构看ModelViewSet共有 6 个父类Day46-60/55.RESTful架构和DRF进阶.md 给出了其类定义其中前 5 个 mixin 父类分别实现对 POST、GET、PUT/PATCH、DELETE、GET 五种操作的支持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每个父类对应的核心方法是Mixin 父类对应操作方法支持的 HTTP 动词业务语义CreateModelMixincreate()POST新增学科RetrieveModelMixinretrieve()GET获取指定学科UpdateModelMixinupdate()/partial_update()PUT / PATCH更新学科DestroyModelMixindestroy()DELETE删除学科ListModelMixinlist()GET获取学科列表由于父类已经实现了这些方法我们几乎没有编写任何业务代码就完成了学科数据全套接口的开发——只需像继承APIView子类时一样声明queryset如何取数据和serializer_class如何序列化数据。3.2 通过DefaultRouter注册路由ModelViewSet相当于多个视图函数的汇总所以不能像普通视图那样直接as_view()需要先创建一个路由器并通过它注册SubjectViewSet再把注册生成的 URL 追加到urlpatternsfrom rest_framework.routers import DefaultRouter router DefaultRouter() router.register(api/subjects, SubjectViewSet) urlpatterns router.urls路由器不仅生成了列表、详情、新建、更新、删除等标准 URL还会自动附加一个.json格式的渲染后缀如果启用这让 ViewSet 的接口地址天然具有 REST 风格。3.3ReadOnlyModelViewSet与只读接口除ModelViewSet外DRF 还提供了ReadOnlyModelViewSet。从名字即可看出它是只读视图的集合——继承它定制的数据接口只能支持 GET 请求也就是获取单个资源和资源列表。这在只需要对外提供查询接口、不需要写操作的场景如展示型数据、报表数据中非常适用。在商业项目示例Day91-100/95.使用Django开发商业项目.md中HouseInfoViewSet正是通过ReadOnlyModelViewSet实现的只读房源接口。4. 数据分页三种内置分页器与自定义分页使用 GET 请求获取资源列表时通常不会一次性加载全部数据除非数据量真的很小。大多数列表类接口都支持分页展示——通过指定页码或类似页码的标识和页面大小一次加载多少条数据来获取不同的数据。分页的实现方式有多种可以手动对QuerySet对象做切片操作也可以利用 Django 框架封装的Paginator和Page对象。使用 DRF 时最方便的做法是在 Django 配置文件中修改REST_FRAMEWORK配置默认分页类和页面大小REST_FRAMEWORK { PAGE_SIZE: 10, DEFAULT_PAGINATION_CLASS: rest_framework.pagination.PageNumberPagination }DRF 内置了三种分页器适用场景各不相同分页器查询参数特点与适用场景PageNumberPaginationpage页码、page_size页面大小最直观适合大多数业务列表接口LimitOffsetPaginationlimit数量、offset偏移量类似 SQL 的 LIMIT/OFFSET适合与已有参数风格一致的系统CursorPaginationcursor游标基于游标的分页避免使用页码分页时暴露网站的数据体量适合数据不断新增、对体量敏感的接口4.1 自定义分页器如果不希望使用配置文件中的默认分页设定可以在视图类中添加pagination_class属性重新指定分页器通常指定为自定义分页器from rest_framework.pagination import PageNumberPagination class CustomizedPagination(PageNumberPagination): # 默认页面大小 page_size 5 # 页面大小对应的查询参数 page_size_query_param size # 页面大小的最大值 max_page_size 50class SubjectView(ListAPIView): # 指定如何获取数据 queryset Subject.objects.all() # 指定如何序列化数据 serializer_class SubjectSerializer # 指定如何分页 pagination_class CustomizedPagination参数语义说明page_size默认页面大小即未显式指定时的每页数据条数page_size_query_param允许客户端通过哪个查询参数覆盖页面大小这里设置为size即请求?page2size20可获取第 2 页、每页 20 条max_page_size客户端能指定的页面大小上限防止一次性请求过量数据这里上限为 50。如果不希望数据分页可以将pagination_class属性设置为None来取消默认的分页器。在 Day91-100/95.使用Django开发商业项目.md 中可以看到HouseTypeViewSet就通过pagination_class None取消了分页因为户型这类数据量很小的资源无需分页。5. 数据筛选重写get_queryset与django-filter5.1 通过重写get_queryset实现请求参数筛选如果需要使用 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__nosno) return queryset except ValueError: raise Http404(No teachers found.)这里有几个值得注意的细节defer(subject)延迟加载外键字段避免在列表场景下不必要的关联查询与入门篇中 FBV 版show_teachers的defer(subject)用法一致通过self.request.GET.get(sno)从查询字符串中读取学科编号使用filter(subject__nosno)完成跨模型字段筛选捕获ValueError并抛出Http404对非法参数返回 404 而不是 500保证接口的健壮性。5.2 用django-filter实现声明式筛选除了手动重写get_queryset还可以使用三方库django-filter配合 DRF 实现数据筛选。先安装pip install django-filter然后在INSTALLED_APPS中注册应用并在REST_FRAMEWORK中配置默认筛选后端这里同时配置了排序后端INSTALLED_APPS [ django_filters, ] REST_FRAMEWORK { DEFAULT_FILTER_BACKENDS: ( django_filters.rest_framework.DjangoFilterBackend, rest_framework.filters.OrderingFilter, ), }上述配置示例引自 Day91-100/95.使用Django开发商业项目.md 中的“过滤数据”小节。为视图类配置filter_backends属性并指定使用DjangoFilterBackend后可以用filter_fields属性或filterset_class属性来指定如何筛选数据。方式一用filter_fields直接声明可按哪些模型字段筛选from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import OrderingFilter from rest_framework.generics import RetrieveAPIView, ListCreateAPIView class EstateView(RetrieveAPIView, ListCreateAPIView): queryset Estate.objects.all().select_related(district).prefetch_related(agents) serializer_class EstateSerializer filter_backends (DjangoFilterBackend, OrderingFilter) filter_fields (name, district) ordering (-hot, ) ordering_fields (hot, estateid)方式二用filterset_class定义更灵活的筛选器支持条件运算模糊匹配、大于等于、小于等于等from django_filters import rest_framework as drf from common.models import HouseInfo class HouseInfoFilter(drf.FilterSet): 自定义房源数据过滤器 title drf.CharFilter(lookup_exprstarts) dist drf.NumberFilter(field_namedistrict) min_price drf.NumberFilter(field_nameprice, lookup_exprgte) max_price drf.NumberFilter(field_nameprice, lookup_exprlte) type drf.NumberFilter() class Meta: model HouseInfo fields (title, district, min_price, max_price, type)以上HouseInfoFilter及其在视图中的挂载示例均引自 Day91-100/95.使用Django开发商业项目.md。然后在视图类中挂载class HouseInfoViewSet(CacheResponseMixin, ReadOnlyModelViewSet): queryset HouseInfo.objects.all() \ .select_related(type, district, estate, agent) \ .prefetch_related(tags).order_by(-pubdate) serializer_class HouseInfoSerializer filter_backends (DjangoFilterBackend, OrderingFilter) filterset_class HouseInfoFilter ordering (price,) ordering_fields (price, area)可以看到filterset_class比起filter_fields表达能力更强CharFilter(lookup_exprstarts)实现标题前缀匹配NumberFilter(field_nameprice, lookup_exprgte)/lte实现价格区间查询min_price、max_price客户端请求形如/api/houses/?min_price100max_price500type3即可完成组合筛选。6. 小结从入门到进阶的接口开发路径综合第 54 天Day46-60/54.RESTful架构和DRF入门.md与本文的内容使用 DRF 定制 RESTful 数据接口已经形成了一条清晰的进阶路径实现方式代码量灵活性适用场景FBV api_view中高逻辑高度定制、返回结构特殊的接口CBV继承ListAPIView等低中标准 CRUD 接口少量定制CBV继承ModelViewSet/ReadOnlyModelViewSet极低中资源完整 CRUD 或只读接口配合DefaultRouter自动生成路由分页 筛选django-filter低高列表类接口的数据体量控制与组合条件查询在完整商业项目中参见 Day91-100/95.使用Django开发商业项目.md这套方法论被整体复用DefaultRouter注册HouseTypeViewSet、HouseInfoViewSet继承ReadOnlyModelViewSet并通过filterset_class实现房源组合筛选再配合缓存、认证等策略构成了前后端分离项目后端 API 的完整骨架。掌握本文的 CBV、ViewSet、分页与筛选四件套也就掌握了 DRF 从入门到进阶的核心能力。赞分享文档教程【免费下载链接】Python-100-DaysPython - 100天从新手到大师项目地址https://gitcode.com/GitHub_Trending/py/Python-100-Days点击查看免费下载相关推荐mesop表格组件进阶排序、筛选与分页全实现mesop表格组件进阶排序、筛选与分页全实现 引言 你还在为Python Web应用中的表格功能实现而烦恼吗从基础的数据展示到复杂的排序、筛选和分页Mes前端后端Web框架WinUIEx自定义背景效果创建视觉震撼的Windows应用界面终极指南WinUIEx自定义背景效果创建视觉震撼的Windows应用界面终极指南 想要为你的Windows应用添加令人惊艳的视觉效果吗WinUIEx提供了强大的自定UI库/组件JAWS核心功能深度解析从网络信息到服务漏洞的完整检测清单JAWS核心功能深度解析从网络信息到服务漏洞的完整检测清单 JAWS Just Another Windows Enum Script是一款专为渗透测试和上一篇3步找回压缩包密码ArchivePasswordTestTool完整使用指南下一篇5分钟掌握yuzu模拟器在电脑畅玩Switch游戏的终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考