Django REST Framework 项目教程:从零构建企业级REST API
2026-01-22 04:29:53作者:凤尚柏Louis
还在为Django项目构建API而烦恼?本文将带你全面掌握Django REST Framework,构建强大、可维护的RESTful API服务。
前言:为什么选择Django REST Framework?
Django REST Framework(DRF)是构建Web API的强大工具包,它为Django开发者提供了:
- 🚀 开箱即用的API功能:序列化、视图、路由、认证等
- 👀 可浏览的API界面:极大提升开发体验
- 🔒 完善的安全机制:认证、权限、限流一应俱全
- 📚 丰富的文档支持:自动生成API文档
- 🎯 高度可定制性:从简单到复杂场景都能胜任
通过本教程,你将学会:
- DRF核心组件的使用方法和最佳实践
- 如何设计符合RESTful规范的API
- 实现用户认证和权限控制
- 处理复杂的数据关系和序列化
- 构建可扩展的生产级API架构
环境准备与项目初始化
系统要求
- Python 3.8+
- Django 5.0 或 4.2
- Django REST Framework 最新版本
安装与配置
# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # Windows
# 安装依赖
pip install django djangorestframework
# 创建Django项目
django-admin startproject myproject .
cd myproject
django-admin startapp api
基础配置
在 settings.py 中添加DRF配置:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # DRF核心
'api', # 我们的API应用
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20
}
核心概念深度解析
1. 序列化器(Serializers):数据转换的艺术
序列化器是DRF的核心组件,负责:
- 将复杂数据类型转换为Python原生数据类型
- 验证传入数据的有效性
- 处理数据的创建和更新操作
基础序列化器示例
# api/serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Post, Comment
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'date_joined']
class CommentSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
class Meta:
model = Comment
fields = ['id', 'content', 'author', 'created_at']
class PostSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
comments = CommentSerializer(many=True, read_only=True)
comment_count = serializers.SerializerMethodField()
class Meta:
model = Post
fields = ['id', 'title', 'content', 'author',
'created_at', 'updated_at', 'comments', 'comment_count']
def get_comment_count(self, obj):
return obj.comments.count()
序列化器工作流程
flowchart TD
A[请求数据] --> B[序列化器验证]
B --> C{验证通过?}
C -->|是| D[转换为模型实例]
C -->|否| E[返回错误信息]
D --> F[保存到数据库]
F --> G[返回序列化数据]
E --> H[客户端]
G --> H
2. 视图(Views):API的业务逻辑中心
DRF提供了多种视图类型,满足不同复杂度的需求:
视图类型对比表
| 视图类型 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| APIView | 简单自定义逻辑 | 完全控制 | 需要手动实现CRUD |
| GenericAPIView | 基于类的通用视图 | 代码复用 | 配置较多 |
| ViewSet | 完整CRUD操作 | 高度封装 | 灵活性较低 |
| ModelViewSet | 模型完整操作 | 极简代码 | 定制性有限 |
视图示例代码
# api/views.py
from rest_framework import viewsets, permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Post, Comment
from .serializers import PostSerializer, CommentSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(author=self.request.user)
@action(detail=True, methods=['post'])
def add_comment(self, request, pk=None):
post = self.get_object()
serializer = CommentSerializer(data=request.data)
if serializer.is_valid():
serializer.save(author=request.user, post=post)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CommentViewSet(viewsets.ModelViewSet):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(author=self.request.user)
3. 路由(Routers):API端点的自动化管理
DRF的路由系统自动为ViewSet生成标准的RESTful端点:
# api/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet, CommentViewSet
router = DefaultRouter()
router.register(r'posts', PostViewSet)
router.register(r'comments', CommentViewSet)
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
自动生成的路由端点
/api/posts/ - GET: 列表, POST: 创建
/api/posts/{id}/ - GET: 详情, PUT: 更新, DELETE: 删除
/api/posts/{id}/add_comment/ - POST: 添加评论(自定义动作)
高级特性实战
1. 认证与权限控制
DRF提供了丰富的认证和权限机制:
# 高级权限配置示例
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
自定义权限类
# api/permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
自定义权限:只允许对象的所有者进行编辑
"""
def has_object_permission(self, request, view, obj):
# 读取权限允许所有请求
if request.method in permissions.SAFE_METHODS:
return True
# 写入权限只允许对象的所有者
return obj.author == request.user
2. 过滤与搜索
实现强大的数据过滤功能:
# 安装过滤依赖
pip install django-filter
# settings.py配置
INSTALLED_APPS = [
...,
'django_filters',
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
'rest_framework.filters.OrderingFilter',
]
}
# 视图中的使用
class PostViewSet(viewsets.ModelViewSet):
# ...
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ['author', 'created_at']
search_fields = ['title', 'content']
ordering_fields = ['created_at', 'updated_at']
ordering = ['-created_at']
3. 分页处理
处理大数据集的分页显示:
# 自定义分页类
from rest_framework.pagination import PageNumberPagination
class LargeResultsSetPagination(PageNumberPagination):
page_size = 100
page_size_query_param = 'page_size'
max_page_size = 1000
class StandardResultsSetPagination(PageNumberPagination):
page_size = 20
page_size_query_param = 'page_size'
max_page_size = 100
# 在视图中使用
class PostViewSet(viewsets.ModelViewSet):
pagination_class = StandardResultsSetPagination
# ...
项目实战:博客API系统
让我们构建一个完整的博客API系统,包含以下功能:
- 用户认证和管理
- 文章CRUD操作
- 评论系统
- 标签分类
- 搜索和过滤
数据模型设计
# api/models.py
from django.db import models
from django.contrib.auth.models import User
class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
tags = models.ManyToManyField(Tag, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_published = models.BooleanField(default=False)
class Meta:
ordering = ['-created_at']
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['created_at']
def __str__(self):
return f"Comment by {self.author} on {self.post}"
完整的序列化器配置
# api/serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Post, Comment, Tag
class UserSerializer(serializers.ModelSerializer):
post_count = serializers.SerializerMethodField()
class Meta:
model = User
fields = ['id', 'username', 'email', 'date_joined', 'post_count']
read_only_fields = ['date_joined']
def get_post_count(self, obj):
return obj.post_set.count()
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ['id', 'name', 'created_at']
class CommentSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
class Meta:
model = Comment
fields = ['id', 'content', 'author', 'created_at', 'updated_at']
read_only_fields = ['author', 'created_at', 'updated_at']
class PostSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
comments = CommentSerializer(many=True, read_only=True)
tags = TagSerializer(many=True, read_only=True)
tag_ids = serializers.PrimaryKeyRelatedField(
many=True,
queryset=Tag.objects.all(),
source='tags',
write_only=True
)
comment_count = serializers.SerializerMethodField()
read_time = serializers.SerializerMethodField()
class Meta:
model = Post
fields = [
'id', 'title', 'content', 'author', 'tags', 'tag_ids',
'created_at', 'updated_at', 'is_published',
'comments', 'comment_count', 'read_time'
]
read_only_fields = ['author', 'created_at', 'updated_at']
def get_comment_count(self, obj):
return obj.comments.count()
def get_read_time(self, obj):
# 假设阅读速度为200字/分钟
word_count = len(obj.content.split())
return max(1, round(word_count / 200))
def create(self, validated_data):
tags = validated_data.pop('tags', [])
post = Post.objects.create(**validated_data)
post.tags.set(tags)
return post
def update(self, instance, validated_data):
tags = validated_data.pop('tags', None)
instance = super().update(instance, validated_data)
if tags is not None:
instance.tags.set(tags)
return instance
完整的视图配置
# api/views.py
from rest_framework import viewsets, permissions, status, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend
from django.contrib.auth.models import User
from .models import Post, Comment, Tag
from .serializers import (
PostSerializer, CommentSerializer,
TagSerializer, UserSerializer
)
from .permissions import IsOwnerOrReadOnly
from .pagination import StandardResultsSetPagination
class UserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
pagination_class = StandardResultsSetPagination
class TagViewSet(viewsets.ModelViewSet):
queryset = Tag.objects.all()
serializer_class = TagSerializer
permission_classes = [permissions.IsAdminUser]
pagination_class = StandardResultsSetPagination
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
pagination_class = StandardResultsSetPagination
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ['author', 'tags', 'is_published', 'created_at']
search_fields = ['title', 'content']
ordering_fields = ['created_at', 'updated_at', 'title']
ordering = ['-created_at']
def perform_create(self, serializer):
serializer.save(author=self.request.user)
@action(detail=True, methods=['post'])
def publish(self, request, pk=None):
post = self.get_object()
if post.author != request.user and not request.user.is_staff:
return Response(
{'error': '只有作者或管理员可以发布文章'},
status=status.HTTP_403_FORBIDDEN
)
post.is_published = True
post.save()
return Response({'status': '文章已发布'})
@action(detail=True, methods=['post'])
def unpublish(self, request, pk=None):
post = self.get_object()
if post.author != request.user and not request.user.is_staff:
return Response(
{'error': '只有作者或管理员可以取消发布'},
status=status.HTTP_403_FORBIDDEN
)
post.is_published = False
post.save()
return Response({'status': '文章已取消发布'})
@action(detail=False)
def published(self, request):
published_posts = self.get_queryset().filter(is_published=True)
page = self.paginate_queryset(published_posts)
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
class CommentViewSet(viewsets.ModelViewSet):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
pagination_class = StandardResultsSetPagination
def perform_create(self, serializer):
serializer.save(author=self.request.user)
@action(detail=True, methods=['post'])
def like(self, request, pk=None):
comment = self.get_object()
# 实现点赞逻辑
return Response({'status': '点赞成功'})
路由配置
# api/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet, CommentViewSet, TagViewSet, UserViewSet
router = DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'posts', PostViewSet)
router.register(r'comments', CommentViewSet)
router.register(r'tags', TagViewSet)
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
主项目URL配置
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
path('api-auth/', include('rest_framework.urls')),
]
测试与部署
编写单元测试
# api/tests.py
from django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework import status
from django.contrib.auth.models import User
from .models import Post, Tag
class PostAPITestCase(APITestCase):
def setUp(self):
self.user = User.objects.create_user(
username='testuser',
password='testpass123'
)
self.tag = Tag.objects.create(name='Django')
self.post = Post.objects.create(
title='Test Post',
content='Test content',
author=self.user
)
self.post.tags.add(self.tag)
def test_get_posts(self):
url = reverse('post-list')
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_create_post_authenticated(self):
self.client.force_authenticate(user=self.user)
url = reverse('post-list')
data = {
'title': 'New Post',
'content': 'New content',
'tag_ids': [self.tag.id]
}
response = self.client.post(url, data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
def test_create_post_unauthenticated(self):
url = reverse('post-list')
data = {'title': 'New Post', 'content': 'New content'}
response = self.client.post(url, data)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
部署配置
创建生产环境配置:
# settings/production.py
from .base import *
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']
# 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('DB_PORT'),
}
}
# 静态文件配置
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
# 安全配置
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
性能优化与最佳实践
1. 查询优化
# 使用select_related和prefetch_related优化查询
class PostViewSet(viewsets.ModelViewSet):
def get_queryset(self):
return Post.objects.select_related('author').prefetch_related(
'tags', 'comments', 'comments__author'
)
2. 缓存策略
# 使用DRF的缓存扩展
from rest_framework_extensions.cache.mixins import CacheResponseMixin
class CachedPostViewSet(CacheResponseMixin, PostViewSet):
cache_timeout = 60 * 15 # 15分钟缓存
3. 异步处理
# 使用Django的异步支持
from asgiref.sync import async_to_sync
class PostViewSet(viewsets.ModelViewSet):
@action(detail=True, methods=['post'])
@async_to_sync
async def async_action(self, request, pk=None):
# 异步处理逻辑
pass
登录后查看全文
热门项目推荐
相关项目推荐
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5-w4a8GLM-5-w4a8基于混合专家架构,专为复杂系统工程与长周期智能体任务设计。支持单/多节点部署,适配Atlas 800T A3,采用w4a8量化技术,结合vLLM推理优化,高效平衡性能与精度,助力智能应用开发Jinja00
请把这个活动推给顶尖程序员😎本次活动专为懂行的顶尖程序员量身打造,聚焦AtomGit首发开源模型的实际应用与深度测评,拒绝大众化浅层体验,邀请具备扎实技术功底、开源经验或模型测评能力的顶尖开发者,深度参与模型体验、性能测评,通过发布技术帖子、提交测评报告、上传实践项目成果等形式,挖掘模型核心价值,共建AtomGit开源模型生态,彰显顶尖程序员的技术洞察力与实践能力。00
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00
MiniMax-M2.5MiniMax-M2.5开源模型,经数十万复杂环境强化训练,在代码生成、工具调用、办公自动化等经济价值任务中表现卓越。SWE-Bench Verified得分80.2%,Multi-SWE-Bench达51.3%,BrowseComp获76.3%。推理速度比M2.1快37%,与Claude Opus 4.6相当,每小时仅需0.3-1美元,成本仅为同类模型1/10-1/20,为智能应用开发提供高效经济选择。【此简介由AI生成】Python00
Qwen3.5Qwen3.5 昇腾 vLLM 部署教程。Qwen3.5 是 Qwen 系列最新的旗舰多模态模型,采用 MoE(混合专家)架构,在保持强大模型能力的同时显著降低了推理成本。00- RRing-2.5-1TRing-2.5-1T:全球首个基于混合线性注意力架构的开源万亿参数思考模型。Python00
项目优选
收起
deepin linux kernel
C
27
11
OpenHarmony documentation | OpenHarmony开发者文档
Dockerfile
567
3.83 K
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Java
68
20
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
12
1
暂无简介
Dart
798
197
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
1.37 K
779
喝着茶写代码!最易用的自托管一站式代码托管平台,包含Git托管,代码审查,团队协作,软件包和CI/CD。
Go
23
0
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
349
200
Ascend Extension for PyTorch
Python
376
446
无需学习 Kubernetes 的容器平台,在 Kubernetes 上构建、部署、组装和管理应用,无需 K8s 专业知识,全流程图形化管理
Go
16
1