文章目录
-
- [一、DRF 核心架构:先搞懂"骨架"](#一、DRF 核心架构:先搞懂“骨架”)
-
- [1. API 请求生命周期(核心脉络)](#1. API 请求生命周期(核心脉络))
- [2. 核心设计原则](#2. 核心设计原则)
- [二、DRF 核心组件(必掌握)](#二、DRF 核心组件(必掌握))
-
- [1. 序列化组件(Serializers):数据转换与校验的核心](#1. 序列化组件(Serializers):数据转换与校验的核心)
-
- (1)核心作用
- (2)核心序列化器类型
- [(3)核心用法(ModelSerializer 示例)](#(3)核心用法(ModelSerializer 示例))
- (4)关键技巧
- [2. 视图组件(Views/ViewSets):API 逻辑的载体](#2. 视图组件(Views/ViewSets):API 逻辑的载体)
- [3. 路由组件(Routers):URL 与视图的映射](#3. 路由组件(Routers):URL 与视图的映射)
-
- [(1)普通路由(适配 APIView/GenericAPIView)](#(1)普通路由(适配 APIView/GenericAPIView))
- [(2)自动路由(适配 ViewSet/ModelViewSet)](#(2)自动路由(适配 ViewSet/ModelViewSet))
- [4. 认证组件(Authentication):验证请求身份](#4. 认证组件(Authentication):验证请求身份)
- [5. 权限组件(Permissions):控制请求访问权限](#5. 权限组件(Permissions):控制请求访问权限)
- [6. 限流组件(Throttling):控制接口访问频率](#6. 限流组件(Throttling):控制接口访问频率)
- [7. 分页组件(Pagination):处理大数据量列表](#7. 分页组件(Pagination):处理大数据量列表)
- [8. 过滤与排序组件(Filtering & Sorting)](#8. 过滤与排序组件(Filtering & Sorting))
- [三、DRF 进阶特性(提升效率)](#三、DRF 进阶特性(提升效率))
-
- [1. 异常处理(Exception Handling)](#1. 异常处理(Exception Handling))
- [2. 版本控制(Versioning)](#2. 版本控制(Versioning))
- [3. 内容协商(Content Negotiation)](#3. 内容协商(Content Negotiation))
- [四、DRF 最佳实践(避坑指南)](#四、DRF 最佳实践(避坑指南))
-
- [1. 性能优化](#1. 性能优化)
- [2. 代码组织](#2. 代码组织)
- [3. 安全规范](#3. 安全规范)
- [4. 测试](#4. 测试)
- 五、核心总结
DRF 是 Django 生态中最主流的 RESTful API 开发框架,其核心设计理念是 在 Django 原生能力基础上,通过「组件化、可配置、可扩展」的方式,快速构建标准化、高可用的 API 。本文将从「核心架构→核心组件→进阶特性→最佳实践」四层,系统梳理 DRF 的知识体系,兼顾原理与实战。
一、DRF 核心架构:先搞懂"骨架"
DRF 的核心架构围绕「请求-响应生命周期」展开,所有组件都是为了解决生命周期中不同环节的问题。先明确一次 API 请求的完整流程,再拆解组件:
1. API 请求生命周期(核心脉络)
客户端请求 → URL 路由匹配 → 视图(View/ViewSet)处理 → 数据序列化/校验 → 数据库交互 → 响应返回
↓ ↓ ↓ ↓ ↓
路由组件 认证/权限/限流 视图核心逻辑 序列化组件 数据库适配
2. 核心设计原则
- 继承扩展:所有核心组件(视图、序列化器、认证等)都基于"基类+扩展类"设计,保留 Django 原生逻辑,新增 API 能力;
- 配置优先 :通过类属性/配置文件替代硬编码,比如
permission_classes、serializer_class; - 组件解耦:每个核心能力(认证、权限、序列化)都是独立组件,可自由组合/替换;
- RESTful 规范:内置支持 RESTful 核心特性(资源路由、HTTP 方法映射、状态码标准化)。
二、DRF 核心组件(必掌握)
1. 序列化组件(Serializers):数据转换与校验的核心
(1)核心作用
- 数据序列化 :将 Django 模型(Model)实例/查询集转换为 JSON/XML 等可传输格式(
serializer.data); - 数据反序列化 :将客户端传入的原始数据(如 JSON)转换为 Python 字典,并完成数据校验(
serializer.is_valid()); - 数据保存 :校验通过后,通过
serializer.save()完成数据库增/改操作。
(2)核心序列化器类型
| 序列化器类 | 适用场景 | 核心特点 |
|---|---|---|
Serializer |
非模型数据(如登录请求) | 手动定义所有字段,灵活度最高 |
ModelSerializer |
模型数据(90%+场景) | 自动映射模型字段,减少代码 |
ReadOnlyModelSerializer |
仅只读接口(只查不改) | 自动生成只读字段 |
(3)核心用法(ModelSerializer 示例)
python
# serializers.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
# 自定义字段(非模型字段)
author_name = serializers.CharField(source='author.username', read_only=True)
class Meta:
model = Book # 关联模型
fields = ['id', 'title', 'price', 'author', 'author_name'] # 要序列化的字段
# exclude = ['is_deleted'] # 排除字段(二选一:fields/exclude)
read_only_fields = ['id'] # 只读字段(客户端无法修改)
extra_kwargs = { # 字段级配置
'price': {'min_value': 0, 'required': True},
'title': {'max_length': 100}
}
# 自定义字段校验(单字段)
def validate_title(self, value):
if '非法' in value:
raise serializers.ValidationError('标题包含非法内容')
return value
# 自定义全局校验(多字段)
def validate(self, attrs):
if attrs.get('price') > 1000 and attrs.get('title') == '测试':
raise serializers.ValidationError('测试书籍价格不能超过1000')
return attrs
# 自定义保存逻辑(创建/更新)
def create(self, validated_data):
# 自动关联当前登录用户为作者
validated_data['author'] = self.context['request'].user
return super().create(validated_data)
(4)关键技巧
source:指定字段映射的模型属性(支持跨关联查询,如author.username);context:序列化器上下文(默认包含request/view/format,可传递自定义数据);many=True:序列化查询集(多个实例)时必须传;partial=True:支持部分更新(PATCH 请求)。
2. 视图组件(Views/ViewSets):API 逻辑的载体
视图是 DRF 最核心的组件之一,进化路径已在前文详细讲解,这里梳理核心选型原则:
| 视图类型 | 核心能力 | 适用场景 |
|---|---|---|
APIView |
基础API能力(解析、认证、响应) | 非CRUD逻辑(如登录、支付、复杂业务) |
GenericAPIView |
APIView + 通用查询/序列化 | 需自定义CRUD逻辑,复用查询/序列化 |
GenericAPIView + Mixins |
通用视图 + CRUD混入逻辑 | 部分自定义的CRUD(如只需要列表+创建) |
ModelViewSet |
终极封装(全CRUD + 路由自动生成) | 标准RESTful CRUD接口(优先选用) |
ReadOnlyModelViewSet |
仅只读CRUD(列表+详情) | 只查不改的API(如商品列表、新闻详情) |
核心扩展点(自定义视图逻辑)
-
get_queryset():自定义查询集(如过滤当前用户数据、动态条件过滤); -
get_serializer_class():动态切换序列化器(如列表用简易序列化器,详情用完整序列化器); -
perform_create()/perform_update()/perform_destroy():自定义数据保存/删除逻辑; -
action装饰器:自定义非标准动作(如批量删除、导出Excel):pythonfrom rest_framework.decorators import action from rest_framework.response import Response class BookViewSet(ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer # 自定义动作:GET /books/export_excel/ @action(detail=False, methods=['get']) # detail=False → 列表级动作,True→详情级 def export_excel(self, request): # 实现导出Excel逻辑 return Response({'msg': '导出成功'}) # 自定义动作:POST /books/{id}/change_status/ @action(detail=True, methods=['post']) def change_status(self, request, pk=None): book = self.get_object() book.status = request.data.get('status') book.save() return Response(BookSerializer(book).data)
3. 路由组件(Routers):URL 与视图的映射
DRF 提供两种路由方式,适配不同视图类型:
(1)普通路由(适配 APIView/GenericAPIView)
和 Django 原生路由一致,手动映射 URL 到视图的 as_view() 方法:
python
# urls.py
from django.urls import path
from .views import BookListView, BookDetailView
urlpatterns = [
path('books/', BookListView.as_view()), # 列表/创建
path('books/<int:id>/', BookDetailView.as_view()), # 详情/更新/删除
]
(2)自动路由(适配 ViewSet/ModelViewSet)
通过 DefaultRouter/SimpleRouter 自动生成 RESTful 路由,无需手动写每个 URL:
python
# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BookViewSet
router = DefaultRouter()
# 注册视图集:prefix=路由前缀,viewset=视图类,basename=路由名称前缀(用于reverse)
router.register('books', BookViewSet, basename='book')
urlpatterns = [
path('', include(router.urls)), # 自动生成 /books/ 和 /books/{id}/ 路由
]
DefaultRouter:比SimpleRouter多生成根路由(/),返回所有可用路由的列表;basename:当视图中未定义queryset时必须指定,用于生成路由名称。
4. 认证组件(Authentication):验证请求身份
(1)核心作用
验证请求的发起者身份(如用户是否登录、Token是否有效),认证成功后将用户对象赋值给 request.user,未认证则 request.user 为 AnonymousUser。
(2)内置认证类
| 认证类 | 适用场景 | 配置方式 |
|---|---|---|
BasicAuthentication |
简单HTTP基础认证(测试用) | authentication_classes = [BasicAuthentication] |
TokenAuthentication |
基于Token的认证(常用) | 需配合 rest_framework.authtoken 应用 |
SessionAuthentication |
基于Django Session的认证 | 前后端不分离场景(如Django模板+DRF) |
JWTAuthentication |
基于JWT的认证(主流) | 需安装 djangorestframework-simplejwt |
(3)实战配置(Token认证)
python
# 1. 安装依赖(Token认证需)
# INSTALLED_APPS = [..., 'rest_framework.authtoken']
# 2. 全局配置(settings.py)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # 默认Token认证
'rest_framework.authentication.SessionAuthentication', # 兼容Session
],
}
# 3. 视图级配置(覆盖全局)
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
# 仅用Token认证
authentication_classes = [TokenAuthentication]
(4)获取Token(内置接口)
DRF 提供了获取Token的接口,需在urls.py注册:
python
from rest_framework.authtoken import views
urlpatterns += [
path('api-token-auth/', views.obtain_auth_token), # POST 用户名/密码获取Token
]
5. 权限组件(Permissions):控制请求访问权限
(1)核心作用
在认证之后,判断当前用户是否有权限执行请求的操作(如普通用户只能读,管理员可修改)。
(2)内置权限类
| 权限类 | 作用 | 适用场景 |
|---|---|---|
AllowAny |
允许所有用户访问 | 公开接口(如首页、登录) |
IsAuthenticated |
仅认证用户可访问 | 需登录的接口(如个人中心) |
IsAdminUser |
仅管理员(is_staff=True)可访问 | 后台管理接口 |
IsAuthenticatedOrReadOnly |
认证用户可读写,未认证仅可读 | 公开但需登录修改的接口 |
DjangoModelPermissions |
基于Django模型权限(add/change/delete) | 符合Django权限体系的接口 |
(3)实战配置
python
# 1. 全局配置(settings.py)
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 默认权限
],
}
# 2. 视图级配置(覆盖全局)
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
# 仅管理员可修改,普通用户仅可读
permission_classes = [IsAuthenticatedOrReadOnly, IsAdminUser]
# 3. 自定义权限类(核心)
from rest_framework import permissions
class IsBookAuthor(permissions.BasePermission):
"""自定义权限:仅书籍作者可修改/删除"""
def has_object_permission(self, request, view, obj):
# 只读请求(GET/HEAD/OPTIONS)允许所有认证用户
if request.method in permissions.SAFE_METHODS:
return True
# 写请求仅作者可执行
return obj.author == request.user
# 使用自定义权限
class BookViewSet(ModelViewSet):
permission_classes = [IsAuthenticated, IsBookAuthor]
6. 限流组件(Throttling):控制接口访问频率
(1)核心作用
防止接口被恶意刷取,限制用户/IP在指定时间内的请求次数(如每分钟最多10次请求)。
(2)内置限流类
| 限流类 | 作用 |
|---|---|
AnonRateThrottle |
限制未认证用户(按IP)的访问频率 |
UserRateThrottle |
限制认证用户的访问频率 |
ScopedRateThrottle |
按视图的 throttle_scope 区分限流规则 |
(3)实战配置
python
# 1. 全局配置(settings.py)
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day', # 未认证用户:每天100次
'user': '1000/day', # 认证用户:每天1000次
},
}
# 2. 视图级配置
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
# 自定义视图级限流规则
throttle_classes = [ScopedRateThrottle]
throttle_scope = 'books' # 对应settings中的限流规则
# 3. settings补充Scoped限流
REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']['books'] = '50/minute' # 书籍接口每分钟50次
7. 分页组件(Pagination):处理大数据量列表
(1)核心作用
将大查询集拆分为多页返回,避免一次性返回过多数据导致性能问题。
(2)内置分页类
| 分页类 | 特点 | 适用场景 |
|---|---|---|
PageNumberPagination |
页码分页(?page=1&page_size=10) | 常规列表分页 |
LimitOffsetPagination |
偏移分页(?limit=10&offset=20) | 精准定位数据位置 |
CursorPagination |
游标分页(加密游标,只支持排序) | 大数据量(百万级)分页 |
(3)实战配置
python
# 1. 全局配置(settings.py)
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10, # 默认每页10条
}
# 2. 自定义分页类(推荐)
from rest_framework.pagination import PageNumberPagination
class StandardResultsSetPagination(PageNumberPagination):
page_size = 10 # 默认每页10条
page_size_query_param = 'page_size' # 允许客户端自定义每页条数(?page_size=20)
max_page_size = 100 # 客户端最大可自定义的每页条数
# 视图级使用
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = StandardResultsSetPagination
8. 过滤与排序组件(Filtering & Sorting)
(1)过滤:筛选符合条件的数据
需安装 django-filter:pip install django-filter
python
# 1. 配置(settings.py)
INSTALLED_APPS = [..., 'django_filters']
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend', # 基础过滤
'rest_framework.filters.SearchFilter', # 模糊搜索
],
}
# 2. 视图使用
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filterset_fields = ['author', 'price'] # 基础过滤字段(?author=1&price=99)
search_fields = ['title', 'description'] # 模糊搜索字段(?search=Python)
(2)排序:按指定字段排序
python
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [filters.OrderingFilter]
ordering_fields = ['price', 'publish_date'] # 允许排序的字段(?ordering=-price)
ordering = ['-publish_date'] # 默认排序(按发布时间降序)
三、DRF 进阶特性(提升效率)
1. 异常处理(Exception Handling)
DRF 内置标准化异常处理,可自定义异常响应格式:
python
# utils.py
from rest_framework.views import exception_handler
from rest_framework.response import Response
def custom_exception_handler(exc, context):
# 先调用DRF默认的异常处理
response = exception_handler(exc, context)
# 自定义响应格式
if response is not None:
response.data = {
'code': response.status_code,
'msg': response.data.get('detail', '请求失败'),
'data': response.data,
}
return response
# settings.py
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'utils.custom_exception_handler',
}
2. 版本控制(Versioning)
支持多版本API共存(如 /v1/books/、/v2/books/):
python
# settings.py
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1',
'ALLOWED_VERSIONS': ['v1', 'v2'],
'VERSION_PARAM': 'version',
}
# urls.py
path('<version>/books/', BookViewSet.as_view()),
# 视图中获取版本
class BookViewSet(ModelViewSet):
def get_serializer_class(self):
if self.request.version == 'v1':
return BookV1Serializer
return BookV2Serializer
3. 内容协商(Content Negotiation)
DRF 自动根据请求头 Accept 适配响应格式(如 JSON/XML),也可通过URL后缀指定(/books.json):
python
# settings.py
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer', # 默认JSON
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览器可浏览的界面
],
}
四、DRF 最佳实践(避坑指南)
1. 性能优化
-
序列化器中避免嵌套查询:使用
select_related(外键一对一)/prefetch_related(外键一对多)优化查询集;pythonclass BookViewSet(ModelViewSet): def get_queryset(self): return Book.objects.all().select_related('author').prefetch_related('tags') -
避免序列化器中使用复杂计算字段:可缓存或提前计算;
-
分页:大数据量接口必须分页,优先用
CursorPagination。
2. 代码组织
- 序列化器:按模型拆分(如
book_serializers.py),复杂序列化器拆分为列表/详情版; - 视图:优先用
ModelViewSet,自定义逻辑通过get_*/perform_*方法扩展; - 权限/认证:自定义类统一放在
permissions.py/authentication.py中。
3. 安全规范
- 认证:生产环境禁用
BasicAuthentication,优先用 JWT/Token 认证; - 权限:最小权限原则(如普通用户仅可读,作者仅可修改自己的资源);
- 限流:公开接口必须配置限流,防止刷量;
- 数据校验:所有客户端传入数据必须通过序列化器校验,禁止直接入库。
4. 测试
DRF 提供 APITestCase 方便测试API:
python
from rest_framework.test import APITestCase
from django.contrib.auth.models import User
from .models import Book
class BookAPITest(APITestCase):
def setUp(self):
self.user = User.objects.create_user(username='test', password='123456')
self.client.force_authenticate(user=self.user) # 模拟登录
self.book = Book.objects.create(title='Test Book', price=99, author=self.user)
def test_book_list(self):
response = self.client.get('/books/')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data['results']), 1)
五、核心总结
DRF 的知识体系可总结为「1个核心+8大组件+N个进阶特性」:
- 1个核心:围绕 RESTful 规范,以「请求-响应生命周期」为脉络;
- 8大组件:序列化、视图、路由、认证、权限、限流、分页、过滤(解决API开发的核心问题);
- N个进阶:异常处理、版本控制、内容协商等(提升API的健壮性和扩展性)。
学习DRF的关键是「先掌握核心组件的使用,再理解底层原理,最后通过最佳实践优化」------ 优先用 ModelViewSet 快速实现CRUD,遇到自定义需求时,再回退到 APIView/GenericAPIView 扩展,兼顾效率与灵活性。