DRF 性能优化 #
一、性能优化概述 #
1.1 性能瓶颈 #
| 瓶颈 | 原因 | 解决方案 |
|---|---|---|
| 数据库查询 | N+1问题 | select_related/prefetch_related |
| 序列化 | 复杂计算 | 缓存、简化 |
| 网络传输 | 大数据量 | 分页、压缩 |
1.2 优化原则 #
- 减少数据库查询次数
- 减少数据传输量
- 使用缓存
- 异步处理
二、数据库查询优化 #
2.1 select_related #
用于ForeignKey和OneToOne关系:
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.select_related(
'author',
'category'
)
serializer_class = ArticleSerializer
2.2 prefetch_related #
用于ManyToMany和反向关系:
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.prefetch_related(
'tags',
'comments'
)
serializer_class = ArticleSerializer
2.3 组合使用 #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.select_related(
'author',
'category'
).prefetch_related(
'tags',
'comments__author'
)
serializer_class = ArticleSerializer
2.4 only和defer #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.only(
'id', 'title', 'summary', 'created_at'
)
serializer_class = ArticleListSerializer
三、序列化优化 #
3.1 简化序列化器 #
python
class ArticleListSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source='author.username')
class Meta:
model = Article
fields = ['id', 'title', 'author_name', 'created_at']
class ArticleDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
depth = 1
3.2 使用不同序列化器 #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
def get_serializer_class(self):
if self.action == 'list':
return ArticleListSerializer
return ArticleDetailSerializer
3.3 避免嵌套过深 #
python
class ArticleSerializer(serializers.ModelSerializer):
author = serializers.SerializerMethodField()
class Meta:
model = Article
fields = '__all__'
def get_author(self, obj):
return {
'id': obj.author.id,
'username': obj.author.username
}
四、分页优化 #
4.1 使用CursorPagination #
python
from rest_framework.pagination import CursorPagination
class ArticleCursorPagination(CursorPagination):
page_size = 20
ordering = '-created_at'
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
pagination_class = ArticleCursorPagination
4.2 延迟加载 #
python
class ArticleViewSet(viewsets.ModelViewSet):
def get_queryset(self):
if self.action == 'list':
return Article.objects.only('id', 'title', 'created_at')
return Article.objects.all()
五、缓存优化 #
5.1 视图缓存 #
python
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator
class ArticleViewSet(viewsets.ModelViewSet):
@method_decorator(cache_page(60 * 5))
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
5.2 查询缓存 #
python
from django.core.cache import cache
class ArticleViewSet(viewsets.ModelViewSet):
def get_queryset(self):
cache_key = 'articles_queryset'
queryset = cache.get(cache_key)
if queryset is None:
queryset = Article.objects.select_related('author')
cache.set(cache_key, queryset, 60 * 5)
return queryset
六、性能监控 #
6.1 查询计数 #
python
from django.db import connection
from django.db import reset_queries
class QueryCountMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
reset_queries()
response = self.get_response(request)
query_count = len(connection.queries)
response['X-Query-Count'] = str(query_count)
return response
6.2 响应时间 #
python
import time
class TimingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
duration = time.time() - start_time
response['X-Response-Time'] = f'{duration:.3f}s'
return response
七、总结 #
本章学习了DRF性能优化:
- 数据库优化:select_related、prefetch_related
- 序列化优化:简化序列化器
- 分页优化:CursorPagination
- 缓存优化:视图和查询缓存
- 性能监控:查询计数、响应时间
性能优化是构建高性能API的关键!
最后更新:2026-03-28