DRF 性能优化 #

一、性能优化概述 #

1.1 性能瓶颈 #

瓶颈 原因 解决方案
数据库查询 N+1问题 select_related/prefetch_related
序列化 复杂计算 缓存、简化
网络传输 大数据量 分页、压缩

1.2 优化原则 #

  • 减少数据库查询次数
  • 减少数据传输量
  • 使用缓存
  • 异步处理

二、数据库查询优化 #

用于ForeignKey和OneToOne关系:

python
class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.select_related(
        'author',
        'category'
    )
    serializer_class = ArticleSerializer

用于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