Django REST Framework 教程:构建强大 API 的完整指南
Django REST Framework (DRF) 是一个强大而灵活的工具包,用于在 Django 中构建 Web API。它提供了序列化器、视图集、身份验证、权限控制、版本控制等多种功能,使得开发者可以高效地构建 RESTful API,满足各种复杂需求。本教程将深入探讨 Django REST Framework 的各个方面,并提供实际示例,帮助你掌握构建强大 API 的完整指南。
1. Django REST Framework 的优势
在使用 DRF 之前,让我们先了解一下它的优势,这将有助于你更好地理解为什么它如此受欢迎:
- 序列化器 (Serializers): 序列化器可以将 Django 模型实例转换为 JSON、XML 等格式,用于 API 响应。同时,它们也能将 JSON 或 XML 数据转换回模型实例,用于处理 API 请求。 序列化器提供了数据验证功能,确保数据的完整性和一致性。
- 视图集 (ViewSets): 视图集可以将相关的视图逻辑组织在一起,减少代码重复,提高代码的可读性和可维护性。 DRF 提供了多种预定义的视图集,如
ModelViewSet
、ReadOnlyModelViewSet
,可以快速构建 CRUD (创建、读取、更新、删除) API。 - 身份验证 (Authentication): DRF 支持多种身份验证机制,包括基本身份验证、令牌身份验证、OAuth 2.0 等,可以轻松地保护 API 的安全性。
- 权限控制 (Permissions): DRF 提供了灵活的权限控制机制,可以根据用户角色、请求方法等条件控制 API 的访问权限。
- 版本控制 (Versioning): DRF 支持多种 API 版本控制策略,如 URL 路径版本控制、Accept Header 版本控制等,可以方便地维护不同版本的 API。
- 可浏览 API (Browsable API): DRF 自动生成可浏览的 API 界面,方便开发者调试和测试 API。
- 强大的定制性: DRF 提供了大量的可配置选项,可以满足各种定制化需求。
2. 准备工作:安装和配置
在开始使用 DRF 之前,需要先安装它并配置 Django 项目。
-
安装:
bash
pip install djangorestframework -
配置:
-
在 Django 项目的
settings.py
文件中,将rest_framework
添加到INSTALLED_APPS
列表中:
python
INSTALLED_APPS = [
...
'rest_framework',
]
- (可选) 配置全局 DRF 设置。可以在
settings.py
中添加REST_FRAMEWORK
字典,用于配置 DRF 的全局设置,例如默认的身份验证类、权限类等。
python
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated', # 默认需要身份验证
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # 使用 Token 身份验证
'rest_framework.authentication.SessionAuthentication', # 使用 Session 身份验证 (用于可浏览 API)
]
}
3. 创建你的第一个 API:博客文章 API
我们将创建一个简单的博客文章 API 作为示例,演示 DRF 的基本用法。
- 创建 Django 应用:
bash
python manage.py startapp blog
- 定义模型 (models.py):
“`python
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
“`
- 注册模型 (admin.py):
“`python
from django.contrib import admin
from .models import Post
admin.site.register(Post)
“`
- 迁移数据库:
bash
python manage.py makemigrations blog
python manage.py migrate
- 创建序列化器 (serializers.py):
在 blog
应用目录下创建一个 serializers.py
文件,定义 Post
模型的序列化器。
“`python
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ‘all‘ # 或者指定字段 [‘id’, ‘title’, ‘content’, ‘created_at’, ‘updated_at’]
# read_only_fields = [‘created_at’, ‘updated_at’] # 某些字段只读
“`
ModelSerializer
是一个方便的序列化器类,它可以自动从 Django 模型生成字段。 fields = '__all__'
表示序列化所有字段。 read_only_fields
定义了只读字段,这些字段只能在响应中返回,不能通过请求修改。
- 创建视图集 (views.py):
“`python
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [IsAuthenticatedOrReadOnly] # 只有登录用户才能修改,所有人可读
“`
ModelViewSet
提供了一组完整的 CRUD 操作 API,包括创建、读取、更新、删除和列表。 queryset
指定了要序列化的模型对象集合。 serializer_class
指定了使用的序列化器。 permission_classes
指定了访问权限。 IsAuthenticatedOrReadOnly
允许任何人读取数据,但只有经过身份验证的用户才能创建、更新或删除数据。
- 配置 URL (urls.py):
在 blog
应用目录下创建一个 urls.py
文件,配置 API 的 URL。
“`python
from django.urls import path, include
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r’posts’, views.PostViewSet)
urlpatterns = [
path(”, include(router.urls)),
]
“`
DefaultRouter
会自动生成标准 RESTful API 的 URL,例如 /posts/
(列表和创建) 和 /posts/{pk}/
(读取、更新和删除)。
然后在项目级的 urls.py
中包含 blog
应用的 URL。
“`python
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(‘blog.urls’)), # 将 API URL 放在 /api/ 路径下
path(‘api-auth/’, include(‘rest_framework.urls’)) # 用于可浏览API的登录/登出
]
“`
- 启动开发服务器:
bash
python manage.py runserver
现在,你可以在浏览器中访问 http://127.0.0.1:8000/api/posts/
查看博客文章 API。 你会看到一个可浏览的 API 界面,你可以通过它来创建、读取、更新和删除博客文章。 如果设置了 DEFAULT_PERMISSION_CLASSES
,你可能需要登录才能进行修改操作。
4. 序列化器的进阶用法
- 自定义字段 (Custom Fields):
有时,你需要自定义序列化器中的字段,例如将多个字段组合成一个字段,或者对字段的值进行转换。
“`python
class PostSerializer(serializers.ModelSerializer):
author_name = serializers.SerializerMethodField() # 添加一个自定义的只读字段
class Meta:
model = Post
fields = ['id', 'title', 'content', 'created_at', 'updated_at', 'author_name']
def get_author_name(self, obj):
# 假设 Post 模型有一个 author 字段,它是一个 User 实例
# return obj.author.username if obj.author else "Unknown"
return "管理员" # 临时返回
“`
SerializerMethodField
用于创建只读的自定义字段。 你需要定义一个 get_<field_name>
方法来计算字段的值。
- 验证 (Validation):
序列化器提供了强大的验证功能,可以确保数据的有效性。
-
字段级别的验证: 可以在序列化器字段中添加验证器,例如
validators=[validators.MaxLengthValidator(200)]
。 -
序列化器级别的验证: 可以重写
validate
方法来执行更复杂的验证逻辑。“`python
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ‘all‘def validate(self, data): """ 检查标题和内容是否都不为空 """ if not (data.get('title') or data.get('content')): raise serializers.ValidationError("标题和内容不能都为空.") return data
“`
validate
方法接收所有字段的数据作为参数,如果验证失败,应该引发serializers.ValidationError
异常。 -
嵌套序列化器 (Nested Serializers):
如果模型之间存在关联关系,可以使用嵌套序列化器来序列化关联的模型。 假设我们有一个 Category
模型,并且 Post
模型有一个 category
外键指向 Category
模型。
“`python
# models.py
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name=’posts’) # 添加 category 外键
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
# serializers.py
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = [‘id’, ‘name’]
class PostSerializer(serializers.ModelSerializer):
category = CategorySerializer(read_only=True) # 嵌套序列化器,只读
class Meta:
model = Post
fields = ['id', 'title', 'content', 'category', 'created_at', 'updated_at']
“`
CategorySerializer
用于序列化 Category
模型。 在 PostSerializer
中,我们使用 CategorySerializer
作为 category
字段的序列化器。 read_only=True
意味着不能通过 API 请求来修改 category
字段。 如果需要允许通过 API 请求来创建或更新关联的 Category
对象,需要移除 read_only=True
并处理创建和更新的逻辑。
5. 身份验证和权限控制
DRF 提供了多种身份验证和权限控制机制,可以根据需要选择合适的方案。
-
身份验证:
-
SessionAuthentication: 使用 Django 的 Session 机制进行身份验证,主要用于 Web 浏览器访问。
- TokenAuthentication: 使用简单的 Token 进行身份验证,适用于移动应用和客户端。
- JSONWebTokenAuthentication: 使用 JSON Web Token (JWT) 进行身份验证,提供更安全的身份验证机制。 需要安装
djangorestframework-jwt
库。 -
OAuth2Authentication: 使用 OAuth 2.0 协议进行身份验证,适用于第三方应用集成。 需要安装
django-oauth-toolkit
库。 -
权限控制:
-
AllowAny: 允许所有用户访问。
- IsAuthenticated: 只允许经过身份验证的用户访问。
- IsAdminUser: 只允许管理员用户访问。
- IsAuthenticatedOrReadOnly: 允许任何人读取数据,但只有经过身份验证的用户才能创建、更新或删除数据。
- 自定义权限: 可以创建自定义权限类,实现更复杂的权限控制逻辑。
“`python
# permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(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 # 假设 Post 模型有一个 author 字段
“`
“`python
# views.py
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from .permissions import IsOwnerOrReadOnly
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [IsOwnerOrReadOnly] # 应用自定义权限
“`
6. 版本控制
DRF 提供了多种 API 版本控制策略,可以方便地维护不同版本的 API。
- URL 路径版本控制: 在 URL 路径中包含版本号,例如
/api/v1/posts/
。 - Accept Header 版本控制: 在
Accept
请求头中指定版本号。 - 查询参数版本控制: 在查询参数中指定版本号,例如
/api/posts/?version=1
。
7. 测试
编写 API 测试对于确保 API 的正确性和稳定性至关重要。 可以使用 Django 的 TestCase
类和 DRF 的 APIClient
类来编写 API 测试。
“`python
tests.py
from django.test import TestCase
from rest_framework.test import APIClient
from .models import Post
from django.contrib.auth.models import User
class PostAPITests(TestCase):
def setUp(self):
self.client = APIClient()
self.user = User.objects.create_user(username=’testuser’, password=’testpassword’)
self.client.force_authenticate(user=self.user) # 模拟用户登录
self.post = Post.objects.create(title=’Test Post’, content=’Test Content’)
def test_get_post_list(self):
response = self.client.get('/api/posts/')
self.assertEqual(response.status_code, 200)
def test_create_post(self):
data = {'title': 'New Post', 'content': 'New Content'}
response = self.client.post('/api/posts/', data, format='json')
self.assertEqual(response.status_code, 201)
# 更多的测试用例...
“`
8. 总结
Django REST Framework 是一个功能强大的工具包,可以帮助你快速构建高质量的 RESTful API。 本教程涵盖了 DRF 的基本概念和常用功能,包括序列化器、视图集、身份验证、权限控制和版本控制。 通过学习本教程,你将能够掌握 DRF 的核心知识,并将其应用到实际项目中。 持续学习和实践是掌握 DRF 的关键,希望本教程能为你提供一个良好的起点。 祝你使用 Django REST Framework 构建出色的 API!