Django-CSR架构总结Rest framework

这篇讲什么

  • 这篇从架构视角看 DRF:前后端分离(CSR)要解决什么问题、一次请求在 DRF 里怎么从路由走到序列化器再变成 JSON、以及「四行代码定义一个模型的 API」到底成不成立。
  • 涉及的组件行为都按本机 Django 5.2.19 + DRF 3.18.3 实测过。

解决什么问题

  • 给应用提供 RESTful API:前端(Vue/React/小程序)只管展示,后端只管数据与业务,两边靠 JSON 接口通信。
  • 这里的 CSR 指 Client-Side Rendering(客户端渲染),与 SSR(服务端渲染)相对:页面骨架由前端出,数据由 API 给。

DRF 架构之美

  • 简单易用:既可以用自动 CRUD(ModelViewSet + Router),也可以自定义单个接口。
  • 提供可浏览的 HTML API(BrowsableAPIRenderer)。
  • 一套实现同时提供 HTML / JSON 两种表现层(实测 Accept 协商与格式后缀,见《Django-RESTful-Api之请求与响应》)。
  • 灵活的认证:Session / Basic / Token 内置,OAuth、JWT 走第三方(实测 JWT 不在 DRF 本体里)。
  • 权限可组合:AllowAny、IsAuthenticated、IsAuthenticatedOrReadOnly、Django 模型权限、自定义 BasePermission,还有 3.10 起的 AND / OR / NOT。
  • 自带过滤、搜索、排序、分页、版本控制、限流、文档(文档要靠 drf-spectacular)。

「四行代码定义一个模型的 API」到底行不行

  • 老笔记那段的代码是错的(viewsets.ModelviewSet、Userserializ 都是笔误)。修正后实测确实能跑:

    school/views.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from django.contrib.auth.models import User
    from rest_framework import serializers, viewsets


    class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
    model = User
    fields = ["url", "username", "email", "is_staff"]


    class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    school/urls.py
    1
    2
    3
    4
    5
    from rest_framework.routers import DefaultRouter

    router = DefaultRouter()
    router.register(r"users", UserViewSet)
    urlpatterns = [path("", include(router.urls))]
    • 实测生成的路由:user-list = ^vs/users/$、user-detail = ^vs/users/(?P<pk>[^/.]+)/$,GET 列表 200。

    • 但超链接序列化器有前置条件(实测):路由必须能被反解。应用 urls.py 里写了 app_name 时,view_name 要带上命名空间,否则整个接口 500:

      1
      2
      ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name
      "user-detail". You may have failed to include the related model in your API, or ...

    所以「四行」只在没有命名空间、没有权限要求时成立;真实项目还要加认证、权限、分页、过滤四件套(各见对应文章)。

一次请求在 DRF 里走过的路

定义API

整体架构

  1. URL 分发:DefaultRouter 生成的 URLPattern 命中,as_view({"get": "list", ...}) 把 HTTP 方法映射到 ViewSet 动作。
  2. 请求包装:HttpRequest → DRF Request,request.data 由 JSONParser / FormParser / MultiPartParser 解析(实测 Content-Type 不支持时 415)。
  3. 认证:按 authentication_classes 依次尝试,request.user / request.auth 被填上(实测默认只有 Session + Basic)。
  4. 权限:permission_classes 全过才继续;对象级权限在取到对象后再查 has_object_permission(实测列表接口不会走它)。
  5. 过滤/排序/分页:filter_queryset() → paginate_queryset()(实测不显式挂后端时这些参数全被忽略)。
  6. 序列化:get_serializer() → .data(ReturnDict / ReturnList)或 .errors。
  7. 响应与协商:Response 交给 DefaultContentNegotiation 选渲染器(实测 Accept: text/html 得到可浏览页面,application/xml 得到 406)。
  8. 异常:任何 APIException 都过 exception_handler,形状统一成 {"detail": ...} 或字段错误字典。

整体架构与配套件

层次 组件 本机版本 对应文章
路由 DefaultRouter / SimpleRouter DRF 3.18.3 《Django-RESTful-Api之ViewSets和Routers》
视图 ViewSet / generics / APIView 同上 《Django-RESTful-Api之基于类的视图》
序列化 ModelSerializer / HyperlinkedModelSerializer 同上 《Django-RESTful-Api之序列化》
认证权限 TokenAuthentication / IsOwnerOrReadOnly 同上 《Django-RESTful-Api之认证和权限》
过滤 DjangoFilterBackend + SearchFilter + OrderingFilter django-filter 26.2 《Django-RESTful-Api设计风格》
分页 PageNumber / LimitOffset / Cursor DRF 内置 同上
文档 drf-spectacular(OpenAPI 3.0.3) 0.30.0 《Django-常用插件》
缓存/异步 内置 Redis 缓存、Celery redis 8.1.0 / celery 5.6.3 《Django-缓存》《Django-Celery》
部署 WhiteNoise + Gunicorn/uvicorn + Nginx 6.12.0 / 26.2.0 / 0.54.0 第四批(部署与运维)

参考

本文结束 感谢您的阅读
正在加载今日诗词....