Django REST Framework 核心概念与实战详解
Django REST Framework (DRF) 是一个强大而灵活的工具包,用于在 Django 的基础上构建 Web API。它极大地简化了 API 的开发过程,提供了认证、授权、序列化、视图集、路由等一系列开箱即用的功能,让开发者能够专注于业务逻辑而不是底层协议的实现。
本文将深入探讨 DRF 的核心概念,并通过一个实际的例子来演示如何使用 DRF 构建一个简单的 RESTful API。
一、 DRF 核心概念
1. Serializers(序列化器)
序列化器是 DRF 最核心的概念之一,它的主要作用有:
* 序列化 (Serialization):将复杂的 Django 模型实例(或查询集)转换为原生 Python 数据类型(如字典、列表),进而可以轻松地渲染成 JSON、XML 等格式的响应。
* 反序列化 (Deserialization):将接收到的原生 Python 数据类型(通常来自请求体)转换为 Django 模型实例,并进行数据验证。
DRF 提供了多种序列化器:
Serializer: 最基础的序列化器,用于完全自定义字段。ModelSerializer: 最常用的序列化器,它能自动根据 Django 模型生成对应的字段,大大简化了开发。它还支持验证和创建/更新模型实例。ListSerializer: 用于处理模型实例列表的序列化。
示例 (ModelSerializer):
“`python
models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
in_stock = models.BooleanField(default=True)
def __str__(self):
return self.name
serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = [‘id’, ‘name’, ‘description’, ‘price’, ‘in_stock’]
# 或者 fields = ‘all‘
# read_only_fields = [‘id’] # 设置只读字段
“`
2. Requests & Responses(请求与响应)
DRF 扩展了 Django 的 HttpRequest 和 HttpResponse 对象,提供了更强大的功能:
Request对象: DRF 的Request对象继承自 Django 的HttpRequest,但提供了更灵活的请求解析。它能自动处理不同内容类型(如 JSON、XML)的请求体,并通过request.data属性提供解析后的数据。Response对象: DRF 的Response对象继承自 Django 的HttpResponse,允许你将任何可序列化的数据传递给它,并指定内容的渲染器(如 JSONRenderer、BrowsableAPIRenderer)。DRF 会自动将数据渲染成适当的格式。
“`python
from rest_framework.response import Response
from rest_framework.decorators import api_view
@api_view([‘GET’])
def hello_world(request):
return Response({“message”: “Hello, world!”})
“`
3. ViewSets(视图集)与 Routers(路由器)
DRF 的 ViewSet 是基于 APIView 构建的,但它将一组相关的视图逻辑(如 list, retrieve, create, update, destroy)组合在一个类中。ViewSet 不提供直接的 HTTP 方法处理,而是通过 Router 映射到具体的 HTTP 方法。
ViewSet 的优势:
* 代码组织: 将相关操作封装在一个类中,提高代码可读性和可维护性。
* DRY (Don’t Repeat Yourself): 避免重复编写 list, detail, create 等视图逻辑。
* 自动化 URL 配置: 配合 Router 可以自动生成 URL 模式,省去了手动配置的麻烦。
类型:
* ViewSet: 最基础的视图集,需要手动实现 list, retrieve 等方法。
* GenericViewSet: 继承自 ViewSet 和 GenericAPIView,可以混合使用 mixins 来快速构建常用操作。
* ModelViewSet: 最常用的视图集,继承自 GenericViewSet 并混合了所有常用的 mixins (List, Create, Retrieve, Update, Destroy),可以直接与模型关联,实现完整的 CRUD 操作。
Router (路由器):
Router 负责将 ViewSet 自动注册到 URL 模式中。最常用的是 DefaultRouter 和 SimpleRouter。
示例:
“`python
views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
urls.py (在你的 Django 项目的 urls.py 中)
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet
router = DefaultRouter()
router.register(r’products’, ProductViewSet)
urlpatterns = [
path(‘api/’, include(router.urls)),
]
“`
通过上述配置,DefaultRouter 会自动为 ProductViewSet 生成以下 URL 模式:
* /api/products/ (GET, POST) -> list, create
* /api/products/{id}/ (GET, PUT, PATCH, DELETE) -> retrieve, update, partial_update, destroy
4. Authentication(认证)与 Permissions(权限)
DRF 提供了灵活的认证和权限系统来保护你的 API。
- 认证 (Authentication): 识别用户的身份。DRF 支持多种认证方式:
BasicAuthentication: HTTP Basic 认证,通常用于测试或内部服务。TokenAuthentication: 基于 Token 的认证,用户登录后获取 Token,后续请求在Authorization头中携带 Token。SessionAuthentication: 基于 Session 的认证,通常用于与 Django 管理后台或基于浏览器的应用集成。OAuth2Authentication: OAuth2 认证。
- 权限 (Permissions): 决定用户是否有权执行某个操作。DRF 提供了多种权限类:
AllowAny: 允许所有用户访问。IsAuthenticated: 只有认证用户才能访问。IsAdminUser: 只有管理员用户才能访问。IsAuthenticatedOrReadOnly: 认证用户可读写,未认证用户只读。DjangoModelPermissions/DjangoObjectPermissions: 基于 Django 模型权限的权限。- 自定义权限: 可以通过继承
BasePermission类来自定义复杂的权限逻辑。
示例:
“`python
settings.py
REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.TokenAuthentication’, # 全局启用 Token 认证
‘rest_framework.authentication.SessionAuthentication’,
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticatedOrReadOnly’, # 全局权限:认证用户可读写,匿名用户只读
]
}
views.py (局部覆盖)
from rest_framework.permissions import IsAdminUser
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
permission_classes = [IsAdminUser] # 只允许管理员进行所有操作
“`
5. Pagination(分页)与 Filtering(过滤)
DRF 提供了多种分页和过滤机制,用于处理大量数据。
-
分页 (Pagination):
PageNumberPagination: 基于页码的分页。LimitOffsetPagination: 基于限制(limit)和偏移(offset)的分页。CursorPagination: 基于游标的分页,适用于大型数据集和连续滚动。
-
过滤 (Filtering):
DjangoFilterBackend: 最常用的过滤后端,允许你基于模型字段进行过滤。需要安装django-filter。SearchFilter: 提供一个搜索功能,根据指定的字段进行模糊匹配。OrderingFilter: 允许客户端通过查询参数指定结果的排序方式。
示例:
“`python
settings.py
REST_FRAMEWORK = {
# … 其他设置
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
‘PAGE_SIZE’: 10, # 每页10条记录
‘DEFAULT_FILTER_BACKENDS’: [
‘django_filters.rest_framework.DjangoFilterBackend’,
‘rest_framework.filters.SearchFilter’,
‘rest_framework.filters.OrderingFilter’,
]
}
views.py
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = [‘in_stock’, ‘price’] # 允许按库存状态和价格过滤
search_fields = [‘name’, ‘description’] # 允许按名称和描述搜索
ordering_fields = [‘name’, ‘price’] # 允许按名称和价格排序
“`
二、DRF 实战:构建一个简单的产品 API
我们将从零开始,构建一个管理产品的 RESTful API。
1. 项目设置
首先,创建一个 Django 项目和一个应用:
bash
django-admin startproject myproject
cd myproject
python manage.py startapp products
pip install djangorestframework django-filter # 安装 DRF 和 django-filter
在 myproject/settings.py 中注册应用和 DRF:
“`python
myproject/settings.py
INSTALLED_APPS = [
# …
‘rest_framework’,
‘django_filters’, # 注册 django-filter
‘products’,
]
DRF 配置
REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.SessionAuthentication’,
‘rest_framework.authentication.TokenAuthentication’, # 可选,如果需要基于 Token 的认证
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticatedOrReadOnly’,
],
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
‘PAGE_SIZE’: 10,
‘DEFAULT_FILTER_BACKENDS’: [
‘django_filters.rest_framework.DjangoFilterBackend’,
‘rest_framework.filters.SearchFilter’,
‘rest_framework.filters.OrderingFilter’,
]
}
“`
2. 定义模型 (products/models.py)
“`python
products/models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
in_stock = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
def __str__(self):
return self.name
“`
运行数据库迁移:
bash
python manage.py makemigrations products
python manage.py migrate
3. 创建序列化器 (products/serializers.py)
“`python
products/serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ‘all‘ # 包含所有字段
read_only_fields = [‘id’, ‘created_at’, ‘updated_at’] # 设置只读字段
“`
4. 创建视图集 (products/views.py)
“`python
products/views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAdminUser
class ProductViewSet(viewsets.ModelViewSet):
“””
允许用户查看、编辑、创建和删除产品的 API 端点。
“””
queryset = Product.objects.all()
serializer_class = ProductSerializer
permission_classes = [IsAuthenticatedOrReadOnly] # 认证用户可读写,匿名用户只读
# 局部配置过滤和搜索
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ['in_stock', 'price']
search_fields = ['name', 'description']
ordering_fields = ['name', 'price', 'created_at']
# 如果需要更细粒度的权限,例如只有管理员才能创建/更新/删除
def get_permissions(self):
if self.action in ['create', 'update', 'partial_update', 'destroy']:
self.permission_classes = [IsAdminUser]
else:
self.permission_classes = [IsAuthenticatedOrReadOnly]
return super().get_permissions()
“`
5. 配置 URL (myproject/urls.py 和 products/urls.py)
首先,在 products 应用下创建一个 urls.py 文件(如果不存在):
“`python
products/urls.py
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet
router = DefaultRouter()
router.register(r’products’, ProductViewSet, basename=’product’) # basename 是为了解决没有 queryset 的 ViewSet 的反向解析问题
urlpatterns = router.urls
“`
然后,在项目的主 urls.py 中包含这个应用的 URL:
“`python
myproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(‘products.urls’)), # 包含产品 API 的 URL
path(‘api-auth/’, include(‘rest_framework.urls’)), # 包含 DRF 提供的登录/登出 URL,用于 Browsable API
]
“`
6. 测试 API
运行开发服务器:
bash
python manage.py createsuperuser # 创建一个管理员用户用于测试
python manage.py runserver
打开浏览器,访问 http://127.0.0.1:8000/api/products/。
如果一切正常,你将看到 DRF 提供的 Browsable API 界面,可以进行:
* 查看产品列表 (GET)
* 创建新产品 (POST) – 需要登录或使用管理员账户
* 访问 http://127.0.0.1:8000/api/products/1/ 查看、更新、删除单个产品
你也可以使用工具(如 Postman、Insomnia 或 curl)来测试 API。
示例 curl 命令:
- 获取所有产品:
bash
curl http://127.0.0.1:8000/api/products/ - 创建产品 (需要管理员身份或认证 Token):
bash
# 如果使用 Session 认证,需要先登录到 Browsable API
# 如果使用 Token 认证,需要获取 Token 并替换 YOUR_AUTH_TOKEN
curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Token YOUR_AUTH_TOKEN" \
-d '{"name": "New Gadget", "description": "A cool new device.", "price": "99.99", "in_stock": true}' \
http://127.0.0.1:8000/api/products/ - 过滤产品 (例如,过滤库存中且价格低于 100 的产品):
bash
curl "http://127.0.0.1:8000/api/products/?in_stock=true&price__lt=100" - 搜索产品:
bash
curl "http://127.0.0.1:8000/api/products/?search=Gadget" - 排序产品:
bash
curl "http://127.0.0.1:8000/api/products/?ordering=-price" # 按价格降序
总结
Django REST Framework 通过其强大的序列化器、灵活的视图集和路由器、可插拔的认证/权限系统以及便捷的分页/过滤功能,极大地加速了 RESTful API 的开发。理解并熟练运用这些核心概念,将使你能够高效、优雅地构建高性能的 Web API。
这仅仅是 DRF 功能的冰山一角。你可以进一步探索自定义字段、验证器、解析器、渲染器、限流、信号、嵌套序列化器等高级特性,以满足更复杂的业务需求。