Django中间件需通过request对象获取用户和操作信息,但须先判断request.user.is_authenticated再取user.id,关键字段包括path、method、HTTP_USER_AGENT、REMOTE_ADDR(或X_FORWARDED_FOR),POST参数用request.POST.dict(),JSON请求需手动解析body,且严禁在中间件中执行数据库查询。

中间件里怎么拿到用户和请求操作信息
Django 中间件能访问 request 对象,但默认情况下未登录用户 request.user 是 AnonymousUser,直接取 request.user.id 会报 AttributeError。必须先判断认证状态。
关键字段包括:request.path(路径)、request.method(GET/POST)、request.META.get('HTTP_USER_AGENT')(客户端信息)、request.POST 或 request.body(需注意流已读问题)。
- 对 POST/PUT 请求,若要记录参数,优先用
request.POST.dict();若含 JSON,需先json.loads(request.body.decode()) - 避免在中间件里调用
request.user.is_authenticated以外的数据库查询,否则拖慢所有请求 -
request.META.get('REMOTE_ADDR')可能是代理 IP,生产环境建议用request.META.get('HTTP_X_FORWARDED_FOR')并做清洗
审计日志该存到哪?数据库还是文件?
数据库写入最灵活,支持按用户、时间、模块筛选;但高频写入可能成为瓶颈。文件日志简单可靠,但查起来费劲,且并发写入需加锁。
推荐方案:用 Django ORM 写入独立模型(如 AuditLog),并设置 db_table = 'audit_log' 避免迁移干扰主业务表。
立即学习“Python免费学习笔记(深入)”;
- 字段至少包含:
user_id(允许 NULL)、path、method、status_code(从响应中取)、created_at(auto_now_add=True) - 不要在中间件
process_request里保存日志——此时响应还没生成,拿不到状态码;改用process_response或process_exception - 如果用 Celery 异步写日志,注意
request对象不能跨进程传递,需序列化必要字段(如user_id,path)
如何避免审计日志拖慢正常请求
日志写入本身会增加延迟,尤其当数据库慢或磁盘 I/O 高时。核心原则:不阻塞主流程。
- 禁用
save()的force_insert和信号(post_save),避免触发额外逻辑 - 使用
bulk_create()批量写入(适合聚合多个操作),但注意它不触发模型 save 方法和信号 - 对静态资源(
/static/、/media/、/favicon.ico)直接return response不记录,减少无效日志量 - 考虑加简单采样,比如只记录非 GET 请求,或只记录状态码 ≥400 的请求
为什么 audit_log 表容易越跑越大?
没清理机制的日志表半年就能上千万行。Django 自带 django-admin clearsessions 不管审计日志。
- 用
django.core.management.BaseCommand写个定期清理命令,比如删 90 天前的记录:AuditLog.objects.filter(created_at__lt=now() - timedelta(days=90)).delete() - 在数据库层面建分区(PostgreSQL)或按月分表(MySQL),比 ORM 删除更快
- 别依赖
on_delete=models.CASCADE关联用户删除日志——审计要求通常要保留已注销用户的操作痕迹
真正麻烦的是字段设计:一开始没留扩展字段(比如 extra_data JSONField),后面想记接口耗时或请求 ID 就得加 migration,线上执行有风险。


















