My apologies. It appears I do not have the capability to write files to your file system using the available tools. I misinterpreted my capabilities based on the prompt’s instructions.
However, I have successfully generated the article content. I will provide it to you directly in this response:
Django REST Framework (DRF) 教程:从零开始构建RESTful API
引言
在现代Web开发中,构建高效、可扩展且易于维护的API是至关重要的。Django REST Framework (DRF) 是一个强大而灵活的工具包,它基于Django框架,使开发者能够快速构建RESTful Web API。DRF以其出色的序列化、视图抽象、认证和权限管理等功能而闻名,极大地简化了API开发流程。
本教程将引导你从零开始,一步步构建一个简单的RESTful API。我们将涵盖项目设置、数据模型定义、序列化器、视图、URL配置、认证与权限,并讨论一些最佳实践。
环境准备
首先,我们需要设置开发环境并安装必要的依赖。
-
创建项目目录和虚拟环境
“`bash
mkdir myapi_project
cd myapi_project
python -m venv venvLinux/macOS
source venv/bin/activate
Windows
venv\Scripts\activate
“` -
安装 Django 和 Django REST Framework
bash
pip install Django djangorestframework -
创建 Django 项目和应用
bash
django-admin startproject myapi .
python manage.py startapp todo
这里我们创建了一个名为myapi的项目和一个名为todo的应用,用于管理待办事项。 -
配置
settings.py
打开myapi/settings.py文件,将rest_framework和你的应用todo添加到INSTALLED_APPS中。“`python
myapi/settings.py
INSTALLED_APPS = [
# … 其他 Django 应用
‘rest_framework’,
‘todo’, # 你的应用
]可选:配置 DRF 的全局设置,例如默认认证和权限类
REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.SessionAuthentication’,
‘rest_framework.authentication.TokenAuthentication’,
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticatedOrReadOnly’,
],
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
‘PAGE_SIZE’: 10,
}
``IsAuthenticatedOrReadOnly权限表示未经认证的用户只能读取数据,而认证用户可以读写。TokenAuthentication需要额外安装djoser` 或手动生成Token,这里我们先配置,后面会用到。 -
数据库迁移
bash
python manage.py migrate -
创建超级用户 (可选,但推荐)
为了能够访问 Django Admin 和进行测试,创建一个超级用户。bash
python manage.py createsuperuser
定义数据模型 (Models)
在 todo/models.py 中定义我们的待办事项模型。
“`python
todo/models.py
from django.db import models
from django.contrib.auth.models import User
class Todo(models.Model):
title = models.CharField(max_length=100, verbose_name=”标题”)
description = models.TextField(blank=True, null=True, verbose_name=”描述”)
completed = models.BooleanField(default=False, verbose_name=”是否完成”)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=”创建时间”)
updated_at = models.DateTimeField(auto_now=True, verbose_name=”更新时间”)
owner = models.ForeignKey(User, related_name=’todos’, on_delete=models.CASCADE, verbose_name=”所有者”)
class Meta:
ordering = ['created_at']
verbose_name = "待办事项"
verbose_name_plural = "待办事项"
def __str__(self):
return self.title
“`
完成模型定义后,进行数据库迁移:
bash
python manage.py makemigrations todo
python manage.py migrate
序列化器 (Serializers)
序列化器负责将Django模型实例(或其他复杂数据类型)转换为可轻松渲染成JSON、XML等格式的Python数据类型,反之亦然。DRF提供了 ModelSerializer,可以自动从Django模型生成序列化器。
在 todo 应用目录下创建 serializers.py 文件:
“`python
todo/serializers.py
from rest_framework import serializers
from .models import Todo
class TodoSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source=’owner.username’) # 显示所有者的用户名
class Meta:
model = Todo
fields = ['id', 'title', 'description', 'completed', 'created_at', 'updated_at', 'owner']
read_only_fields = ['created_at', 'updated_at'] # 这些字段在创建和更新时不可写
``owner = serializers.ReadOnlyField(source=’owner.username’)
这里,会将owner字段显示为用户名,并且是只读的。read_only_fields确保created_at和updated_at` 字段只由服务器自动管理。
视图 (Views)
视图负责处理API请求并返回响应。DRF提供了多种视图类型,从低级的 APIView 到高级的 ModelViewSet。ModelViewSet 是处理CRUD(创建、读取、更新、删除)操作的最便捷方式,因为它会自动提供所有这些操作。
在 todo/views.py 中添加视图:
“`python
todo/views.py
from rest_framework import viewsets
from rest_framework import permissions
from .models import Todo
from .serializers import TodoSerializer
from .permissions import IsOwnerOrReadOnly # 我们稍后会创建这个权限类
class TodoViewSet(viewsets.ModelViewSet):
“””
这个视图集提供了 list, create, retrieve, update, partial_update 和 destroy 操作。
“””
queryset = Todo.objects.all()
serializer_class = TodoSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
def perform_create(self, serializer):
"""
在创建Todo实例时,将其所有者设置为当前请求的用户。
"""
serializer.save(owner=self.request.user)
def get_queryset(self):
"""
只允许用户查看和编辑他们自己的待办事项,管理员可以查看所有。
"""
if self.request.user.is_superuser:
return Todo.objects.all()
return self.request.user.todos.all()
``ModelViewSet
我们在这里使用了。perform_create方法确保当用户创建一个Todo时,该Todo会自动关联到当前认证的用户。get_queryset` 方法则实现了用户只能看到和修改自己的Todo项的逻辑。
权限 (Permissions)
为了实现用户只能修改自己的待办事项,我们需要创建一个自定义权限类。
在 todo 应用目录下创建 permissions.py 文件:
“`python
todo/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.owner == request.user
``IsOwnerOrReadOnly
这个权限类确保了只有Todo项的owner` 才能进行修改或删除操作,而其他用户(包括未认证用户)只能查看。
URL配置 (URL Configuration)
现在我们需要将视图映射到URL。DRF的 Router 可以非常方便地为 ViewSet 生成URL。
-
在
todo应用中创建urls.py“`python
todo/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views创建一个路由器并注册我们的视图集
router = DefaultRouter()
router.register(r’todos’, views.TodoViewSet, basename=’todo’)API URL现在由路由器自动确定。
urlpatterns = [
path(”, include(router.urls)),
]
“` -
将应用URL包含到项目URL中
打开myapi/urls.py文件,将todo应用的URL包含进来,并添加DRF的登录/登出URL(用于可浏览API)。“`python
myapi/urls.py
from django.contrib import admin
from django.urls import path, includeurlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(‘todo.urls’)), # 包含 todo 应用的 API URL
path(‘api-auth/’, include(‘rest_framework.urls’)), # 用于可浏览API的登录/登出
]
“`
运行服务器并测试
现在,我们已经完成了API的基本构建。运行开发服务器:
bash
python manage.py runserver
打开浏览器,访问 http://127.0.0.1:8000/api/todos/。你会看到DRF提供的可浏览API界面。
-
创建待办事项:
如果你没有登录,你只能看到空的列表。登录后(通过右上角的 “Login” 或在/admin/创建用户并登录),你就可以在表单中创建新的待办事项。由于我们设置了owner=self.request.user,新创建的Todo会自动关联到你登录的用户。 -
查看和编辑:
你可以点击单个Todo项的URL(例如http://127.0.0.1:8000/api/todos/1/)来查看、更新或删除它。如果你尝试修改一个不属于你的Todo项,你会收到403 Forbidden错误,因为IsOwnerOrReadOnly权限生效了。
认证与权限深入
在 settings.py 中,我们配置了 SessionAuthentication 和 TokenAuthentication。
- SessionAuthentication: 这是Django默认的认证方式,适用于基于Web会话的认证(例如,通过浏览器访问可浏览API)。
- TokenAuthentication: 适用于无状态的API客户端(例如移动应用或SPA)。要使用它,你需要为用户生成一个Token。
安装 djangorestframework-simplejwt 来实现JWT认证 (更推荐用于现代API):
bash
pip install djangorestframework-simplejwt
然后更新 settings.py:
“`python
myapi/settings.py
…
INSTALLED_APPS = [
# …
‘rest_framework.authtoken’, # 如果使用TokenAuthentication
‘rest_framework_simplejwt’, # 如果使用simplejwt
]
REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.SessionAuthentication’,
# ‘rest_framework.authentication.TokenAuthentication’, # 如果使用DRF自带的Token
‘rest_framework_simplejwt.authentication.JWTAuthentication’, # 如果使用simplejwt
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticatedOrReadOnly’,
],
# …
}
simplejwt配置
from datetime import timedelta
SIMPLE_JWT = {
‘ACCESS_TOKEN_LIFETIME’: timedelta(minutes=5),
‘REFRESH_TOKEN_LIFETIME’: timedelta(days=1),
‘ROTATE_REFRESH_TOKENS’: False,
‘BLACKLIST_AFTER_ROTATION’: True,
‘UPDATE_LAST_LOGIN’: False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY, # 使用Django的SECRET_KEY
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
“`
在 myapi/urls.py 中添加JWT认证的URL:
“`python
myapi/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView,
)
urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(‘todo.urls’)),
path(‘api-auth/’, include(‘rest_framework.urls’)),
# JWT认证URL
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
]
“`
现在你可以通过向 /api/token/ 发送用户名和密码来获取JWT Token,然后在请求头中使用 Authorization: Bearer <your_access_token> 进行认证。
更多高级特性和最佳实践
- 分页 (Pagination): 在
settings.py中已经配置了默认分页,你也可以在视图中自定义分页类。 - 过滤 (Filtering): 使用
django-filter库可以轻松为你的API添加过滤功能。 - 搜索 (Search): DRF提供了
SearchFilter,可以用于简单的字段搜索。 - 性能优化:
- N+1查询问题: 在
get_queryset中使用select_related或prefetch_related来优化查询。 - 缓存: 使用Django的缓存机制来减少数据库负载。
- N+1查询问题: 在
- API文档: 使用
drf-yasg或drf-spectacular等工具自动生成Swagger/OpenAPI文档。 - 测试: 编写单元测试和集成测试,确保你的API按预期工作。DRF提供了
APITestCase来方便地测试API。
总结
本教程从零开始,详细介绍了使用Django REST Framework构建一个RESTful API的全过程。我们涵盖了项目设置、数据模型、序列化器、视图、URL配置,以及认证和权限管理。DRF的强大功能和灵活性使其成为Python生态系统中最受欢迎的API构建工具之一。通过不断实践和探索其高级特性,你将能够构建出任何复杂度的健壮API。
希望这篇教程对你有所帮助!祝你在DRF的旅程中一切顺利!