Chapter 09

Django REST Framework

DRF 是 Django 生态构建 RESTful API 的事实标准。序列化、视图集、路由、认证、分页一应俱全,几十行代码交付一套 API。

9.1 DRF 是什么

Django REST Framework(DRF)是最流行的 Django API 工具包。它复用 Django 的 ORM、认证、权限,把「模型 → JSON」的序列化、视图、路由做成可组合的高层组件,并附带浏览器可视化 API 调试界面。

Serializer(序列化器)
DRF 的核心,双向转换:模型/QuerySet ↔ JSON。同时承担输入校验,相当于 API 版的 Form。
ModelSerializer
从模型自动推导字段的序列化器,类似 ModelForm,少写大量样板。
APIView
DRF 的类视图基类,方法名对应 HTTP 动词(get/post),返回 Response 对象。
ViewSet
把一组相关操作(list/retrieve/create/update/destroy)聚成一个类,配合 Router 自动生成路由。
Router(路由器)
为 ViewSet 自动注册全套 RESTful URL,免手写每条 path。
认证(Authentication)
识别请求来自谁:Session、Token、JWT。区别于「权限」(能做什么)。
分页(Pagination)
大列表分批返回,DRF 内置 PageNumber/LimitOffset/Cursor 三种分页风格。

9.2 安装与配置

$ pip install djangorestframework

# settings.py
INSTALLED_APPS += ["rest_framework"]

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.TokenAuthentication",
    ],
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticatedOrReadOnly",
    ],
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
    "PAGE_SIZE": 10,
}

9.3 Serializer

# blog/serializers.py
from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source="category.name", read_only=True)

    class Meta:
        model = Post
        fields = ["id", "title", "body", "category", "category_name", "published"]
        read_only_fields = ["id"]

    def validate_title(self, value):
        if len(value) < 3:
            raise serializers.ValidationError("标题太短")
        return value

9.4 ViewSet + Router:几行搞定 CRUD API

# blog/api.py
from rest_framework import viewsets, permissions
from .models import Post
from .serializers import PostSerializer

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
# blog/urls_api.py
from rest_framework.routers import DefaultRouter
from .api import PostViewSet

router = DefaultRouter()
router.register("posts", PostViewSet)

urlpatterns = router.urls
# 自动得到:
#  GET/POST      /posts/
#  GET/PUT/DELETE /posts/{id}/
ModelViewSet 的威力

一个 ModelViewSet + Router 注册,就自动实现了列表、创建、详情、更新、删除五个端点,还带分页与浏览器可调试界面。这是 DRF「快速构建 API」口号的底气。

9.5 用 APIView 精细控制

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class PostList(APIView):
    def get(self, request):
        posts = Post.objects.all()
        ser = PostSerializer(posts, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = PostSerializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return Response(ser.data, status=status.HTTP_201_CREATED)

9.6 认证:Token 与 JWT

方式特点适用
Session基于 cookie,同域前后端同站页面
TokenDRF 内置,一用户一 token简单 App
JWT无状态、自带过期与刷新前后端分离/微服务
# JWT(djangorestframework-simplejwt)
$ pip install djangorestframework-simplejwt

from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

urlpatterns += [
    path("api/token/", TokenObtainPairView.as_view()),
    path("api/token/refresh/", TokenRefreshView.as_view()),
]

9.7 权限与分页

# 内置权限类
#  AllowAny / IsAuthenticated / IsAdminUser
#  IsAuthenticatedOrReadOnly

# 自定义对象级权限:只有作者能改
from rest_framework import permissions

class IsAuthor(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.author == request.user
认证 ≠ 权限

认证回答「你是谁」,权限回答「你能做什么」。DRF 先跑认证识别用户,再用权限类判定是否放行。二者需分别配置,缺一不可。

9.8 小结与下一步