系列:Python Web 框架
Django 本身是全栈框架,模板、表单、后台管理都很强。但很多项目后来会走向前后端分离:前端用 Vue、React 或小程序,后端只提供 JSON API。
这时候常用的方案就是 Django REST Framework,简称 DRF。
它不是 Django 的一个小插件,而是一整套 API 开发工具:序列化器、视图、路由、权限、认证、分页、过滤、可浏览 API 页面都给你准备好了。你可以理解为:Django 负责数据库、模型、配置和生态,DRF 负责把它们变成 API。
这篇默认你已经看过 Django 安装与使用指南,至少知道 project、app、model、migration 是什么。
安装和准备项目
在已有 Django 项目里安装:
pip install djangorestframework把 rest_framework 加进 INSTALLED_APPS:
INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "rest_framework", "blog",]下面用一个最普通的文章模型做例子。
blog/models.py:
from django.db import models
class Article(models.Model): title = models.CharField(max_length=120) slug = models.SlugField(unique=True) body = models.TextField() published = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True)
def __str__(self): return self.title迁移:
python manage.py makemigrationspython manage.py migrateSerializer:把模型变成 JSON
DRF 里最核心的概念是 Serializer。它负责两件事:
- 把 Django model 转成 JSON;
- 把请求里的 JSON 校验后转成 Python 数据。
创建 blog/serializers.py:
from rest_framework import serializersfrom .models import Article
class ArticleSerializer(serializers.ModelSerializer): class Meta: model = Article fields = ["id", "title", "slug", "body", "published", "created_at"] read_only_fields = ["id", "created_at"]这段代码看起来像 Django Form,但它面向 API。read_only_fields 的意思是客户端不能传这些字段来改。
如果你不想暴露完整正文,也可以拆两个 Serializer:
class ArticleListSerializer(serializers.ModelSerializer): class Meta: model = Article fields = ["id", "title", "slug", "published", "created_at"]列表页用轻量字段,详情页再返回正文,这是实际项目里很常见的优化。
ViewSet:少写重复 CRUD
DRF 可以用函数视图、类视图,也可以用 ViewSet。入门阶段建议先用 ViewSet,它能少写很多重复代码。
blog/views.py:
from rest_framework import viewsetsfrom .models import Articlefrom .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.all().order_by("-created_at") serializer_class = ArticleSerializer这几行代码已经有了完整 CRUD:
GET /api/articles/ 列表POST /api/articles/ 创建GET /api/articles/1/ 详情PUT /api/articles/1/ 全量更新PATCH /api/articles/1/ 部分更新DELETE /api/articles/1/ 删除这就是 DRF 的生产力来源。
Router:自动生成 URL
mysite/urls.py:
from django.contrib import adminfrom django.urls import include, pathfrom rest_framework.routers import DefaultRouterfrom blog.views import ArticleViewSet
router = DefaultRouter()router.register("articles", ArticleViewSet, basename="article")
urlpatterns = [ path("admin/", admin.site.urls), path("api/", include(router.urls)),]启动:
python manage.py runserver打开 http://127.0.0.1:8000/api/articles/,你会看到 DRF 自带的可浏览 API 页面。它不是给最终用户用的,但开发调试很方便。
权限:不要默认全部开放
上面的 ModelViewSet 默认比较宽松。真实项目里至少要先限制写操作。
最简单的规则:游客可以看,登录用户才能改。
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.all().order_by("-created_at") serializer_class = ArticleSerializer permission_classes = [IsAuthenticatedOrReadOnly]如果要全站默认配置:
REST_FRAMEWORK = { "DEFAULT_PERMISSION_CLASSES": [ "rest_framework.permissions.IsAuthenticatedOrReadOnly", ],}我更建议在项目早期就写清权限,不要等 API 做完了再补。权限后补很容易漏。
分页和过滤
列表接口不分页是一个常见坑。数据少时没感觉,数据一多接口会突然变慢。
settings.py:
REST_FRAMEWORK = { "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", "PAGE_SIZE": 20,}简单搜索可以先手写:
class ArticleViewSet(viewsets.ModelViewSet): serializer_class = ArticleSerializer permission_classes = [IsAuthenticatedOrReadOnly]
def get_queryset(self): queryset = Article.objects.all().order_by("-created_at") keyword = self.request.query_params.get("q") if keyword: queryset = queryset.filter(title__icontains=keyword) return queryset如果过滤条件很多,再考虑 django-filter。不要为了两个查询参数一上来就引入一堆抽象。
常见问题
Serializer 和 ModelForm 有什么区别
ModelForm 面向 HTML 表单,Serializer 面向 API 数据。它们都做校验,但输出目标不同。
如果你在做前后端分离接口,用 Serializer;如果你在做 Django 模板页面,用 Form 或 ModelForm。
ViewSet 会不会太魔法
会有一点。它把 CRUD 约定都封装起来了,所以入门很舒服,但出了复杂需求要知道怎么覆盖。
常见覆盖点:
def get_queryset(self): ...
def get_serializer_class(self): ...
def perform_create(self, serializer): serializer.save(author=self.request.user)项目复杂后,不要把业务全塞进 ViewSet。ViewSet 负责 HTTP 层,真正的业务逻辑可以放到 service 函数里。
DRF 和 FastAPI 怎么选
如果你已经在 Django 生态里,需要 admin、ORM、权限和成熟插件,DRF 很合适。
如果你是从零写一个纯 API 服务,而且非常依赖类型提示和 OpenAPI 文档,FastAPI 安装与使用指南 会更轻。
更完整的取舍可以看 Django 与 FastAPI 对比:如何选择合适的 Python Web 框架。
API 文档怎么办
DRF 自带可浏览 API,但不是正式的 OpenAPI 文档体验。生产项目常见选择是 drf-spectacular:
pip install drf-spectacular然后按 drf-spectacular 文档 配置 schema 和 Swagger UI。
总结
DRF 的价值是把 Django 的成熟生态接到 API 开发上。
最小可用路径是:
Model 定义数据Serializer 做输入输出转换ViewSet 处理 CRUDRouter 生成 URLPermission 限制访问Pagination 保护列表接口如果你已经有 Django 项目,DRF 是很自然的下一步;如果你从零开始做纯 API,要认真比较一下 FastAPI。Django + DRF 的优势是稳和完整,代价是写法更重。更多细节可以看 Django REST Framework 官方文档。