中级Django后端开发者创建大型Web应用需学习的进阶优化知识
Django大型应用进阶实践指南
针对中级开发者,以下是优化查询、扩展功能的核心进阶方向,每个点都附带实操细节:
一、查询性能优化
这是大型应用的核心痛点,直接影响用户体验和服务器负载:
- 进阶使用
select_related/prefetch_related:- 对多对多、反向外键场景,用
Prefetch对象定制预取逻辑,比如过滤预取的关联数据:from django.db.models import Prefetch active_orders = Order.objects.filter(status='active') users = User.objects.prefetch_related( Prefetch('orders', queryset=active_orders, to_attr='active_orders') ) - 避免N+1查询的同时,不要过度预取无关数据,根据视图需求精准控制。
- 对多对多、反向外键场景,用
- 数据库索引高级设计:
- 给频繁过滤、排序的字段加索引,比如
models.Index(fields=['created_at', 'status']) - 用部分索引优化特定场景(PostgreSQL支持):比如给未删除的订单创建索引:
models.Index(fields=['user_id'], condition=models.Q(is_deleted=False), name='active_orders_user_idx') - 函数索引:对字段的函数结果加索引,比如
models.Index(fields=['lower(username)'], name='username_lower_idx')
- 给频繁过滤、排序的字段加索引,比如
- 批量操作与惰性求值:
- 用
bulk_create()/bulk_update()替代循环save(),注意:不会触发信号,auto_now_add需手动赋值 - 处理超大QuerySet时用
iterator()减少内存占用:for obj in LargeModel.objects.iterator(chunk_size=1000):
- 用
- 复杂查询构造:
- 用
Subquery和OuterRef实现子查询,避免多表JOIN的性能损耗:from django.db.models import Subquery, OuterRef latest_order = Order.objects.filter(user=OuterRef('pk')).order_by('-id')[:1] users = User.objects.annotate(latest_order_id=Subquery(latest_order.values('id'))) - 用
annotate结合聚合函数做分组统计,比如按用户统计订单总数:User.objects.annotate(order_count=models.Count('orders'))
- 用
二、高级模型与数据层技巧
- 模型继承与抽象基类:
- 用抽象基类封装通用字段(比如
created_at、updated_at):class BaseModel(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: abstract = True - 避免滥用多表继承,优先用抽象基类或代理模型;代理模型适合给同一表添加不同的管理器或方法:
class ActiveUser(User): class Meta: proxy = True ordering = ['-last_login'] @classmethod def get_active(cls): return cls.objects.filter(is_active=True)
- 用抽象基类封装通用字段(比如
- 信号的合理使用:
- 自定义信号处理业务解耦,比如订单发货时触发通知:
from django.dispatch import Signal, receiver order_shipped = Signal(providing_args=['order', 'tracking']) @receiver(order_shipped) def notify_user(sender, **kwargs): # 发送邮件/短信逻辑 - 注意信号的性能问题:避免在信号中做耗时操作,优先用异步任务处理;不要依赖信号做核心业务逻辑(比如数据一致性)
- 自定义信号处理业务解耦,比如订单发货时触发通知:
- 事务精细控制:
- 嵌套事务用保存点:
with transaction.atomic()嵌套时,内层会创建保存点,失败只回滚内层 - 手动控制事务:用
transaction.savepoint()/transaction.savepoint_rollback()处理部分回滚场景
- 嵌套事务用保存点:
- 数据库路由:
- 配置多数据库路由,实现读写分离或分库分表:
class ReadWriteRouter: def db_for_read(self, model, **hints): return 'replica' def db_for_write(self, model, **hints): return 'default'
- 配置多数据库路由,实现读写分离或分库分表:
三、DRF深度扩展
- 自定义权限与节流:
- 基于对象的权限控制:比如只有订单所有者能修改订单:
class IsOrderOwner(permissions.BasePermission): def has_object_permission(self, request, view, obj): return obj.user == request.user - 自定义节流类:比如给VIP用户更高的请求限额:
class VIPRateThrottle(UserRateThrottle): scope = 'vip' def get_rate(self): if request.user.is_vip: return '1000/day' return '100/day'
- 基于对象的权限控制:比如只有订单所有者能修改订单:
- 动态序列化器与视图集:
- 根据请求参数切换序列化器字段:
class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'username'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.context['request'].query_params.get('include_email'): self.fields['email'] = serializers.EmailField() - 视图集的自定义动作:比如给
UserViewSet添加reset_password动作:@action(detail=True, methods=['post']) def reset_password(self, request, pk=None): user = self.get_object() # 重置密码逻辑 return Response({'status': 'password reset'})
- 根据请求参数切换序列化器字段:
- 大数据量分页:
- 用游标分页替代偏移分页,避免大数据量时的性能问题:
class LargeResultsSetPagination(pagination.CursorPagination): page_size = 100 ordering = '-created_at'
- 用游标分页替代偏移分页,避免大数据量时的性能问题:
四、应用架构与性能扩展
- 异步任务与Celery:
- 用Celery处理耗时任务(比如发送邮件、生成报表),配置任务优先级、定时任务:
@app.task(priority=5) def generate_monthly_report(user_id): # 生成报表逻辑 - 用Celery Beat配置复杂定时任务,比如每周一凌晨生成报表
- 用Celery处理耗时任务(比如发送邮件、生成报表),配置任务优先级、定时任务:
- 缓存分层策略:
- 页面缓存:用
django.views.decorators.cache.cache_page缓存整个视图响应 - 模板片段缓存:用
{% load cache %}{% cache 300 user_stats user.id %}缓存用户统计模块 - 数据缓存:用
cache.set()/cache.get()缓存QuerySet或计算结果,注意缓存失效策略
- 页面缓存:用
- 异步视图:
- 用Django的异步视图处理IO密集型请求(比如调用外部API):
async def async_external_api_view(request): response = await aiohttp.request('GET', 'https://api.example.com/data') data = await response.json() return JsonResponse(data)
- 用Django的异步视图处理IO密集型请求(比如调用外部API):
五、安全与稳定性
- 安全防护进阶:
- CSRF防护:AJAX请求用
{% csrf_token %}生成的token放在请求头X-CSRFToken中 - XSS防护:避免手动渲染HTML,用Django模板自动转义;如果需要渲染富文本,用
bleach库过滤标签 - 自定义密码验证器:比如要求密码包含特殊字符:
class SpecialCharValidator: def validate(self, password, user=None): if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password): raise ValidationError("密码必须包含特殊字符") def get_help_text(self): return "密码必须包含至少一个特殊字符"
- CSRF防护:AJAX请求用
- 日志与监控:
- 配置结构化日志(比如JSON格式),方便日志系统分析
- 自定义异常处理器:捕获DRF的异常并返回统一格式的错误响应:
def custom_exception_handler(exc, context): response = exception_handler(exc, context) if response is not None: response.data['error_code'] = response.status_code return response
内容的提问来源于stack exchange,提问作者Mujeeb
相关产品推荐
相关产品推荐

