如何在Django中记录用户媒体文件访问(下载)的审计日志?
嘿,作为Django开发者,我完全理解你作为新手的困惑——这个需求其实非常常见,而且实现起来并不复杂!我来给你拆解几个可行的思路,一步步来:
核心思路:拦截媒体访问请求并记录日志
默认情况下,Django会让Nginx/Apache这类web服务器直接处理媒体文件的请求,所以要捕获审计日志,我们需要把媒体请求的处理逻辑收回到Django中,或者通过中间件/信号来监听操作。下面是几个最常用的实现方案:
方案一:自定义视图处理媒体下载(最推荐,适合新手)
这个方法最直观,通过Django视图来处理所有媒体文件的下载请求,这样就能在视图里轻松记录日志。
步骤1:创建审计日志模型
首先在你的app里定义一个AuditLog模型,用来存储审计信息:
# models.py from django.db import models from django.contrib.auth.models import User from django.utils.timezone import now class AuditLog(models.Model): user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) # 如果有专门的媒体文件模型,这里可以关联外键,比如MediaFile media_path = models.CharField(max_length=255) action = models.CharField(max_length=50, default='下载') access_time = models.DateTimeField(default=now) ip_address = models.CharField(max_length=50) user_agent = models.CharField(max_length=255, blank=True) def __str__(self): return f"{self.user.username if self.user else '匿名用户'} 于 {self.access_time} 下载 {self.media_path}"
然后执行python manage.py makemigrations和migrate创建数据库表。
步骤2:编写下载视图
写一个视图函数,负责返回媒体文件,同时在返回前记录审计日志:
# views.py from django.http import FileResponse, Http404 from django.contrib.auth.decorators import login_required from django.conf import settings from .models import AuditLog, MediaFile # 假设你有MediaFile模型管理媒体文件 import os @login_required # 如果允许匿名访问,可以去掉这个装饰器 def download_media(request, file_id): try: media = MediaFile.objects.get(id=file_id) file_full_path = os.path.join(settings.MEDIA_ROOT, media.file.name) # 记录审计日志 AuditLog.objects.create( user=request.user, media_path=media.file.name, ip_address=request.META.get('REMOTE_ADDR'), user_agent=request.META.get('HTTP_USER_AGENT', '') ) # 返回文件下载响应 return FileResponse(open(file_full_path, 'rb'), as_attachment=True, filename=media.file.name) except MediaFile.DoesNotExist: raise Http404("媒体文件不存在")
步骤3:配置URL路由
把下载请求指向这个视图:
# urls.py from django.urls import path from . import views urlpatterns = [ # 其他路由... path('media/download/<int:file_id>/', views.download_media, name='download_media'), ]
关键注意事项
- 生产环境中,要确保用户不能直接通过
/media/路径访问文件(比如Nginx配置里限制直接访问MEDIA_ROOT,只允许Django转发的请求),否则日志会漏掉直接访问的情况。 - 如果允许匿名用户下载,记得去掉
@login_required,并处理request.user为匿名的情况(比如user=None)。
方案二:使用中间件捕获所有媒体访问请求
如果你需要捕获所有指向媒体文件的请求(包括直接在浏览器打开的情况),可以用Django中间件来拦截请求并记录日志。不过要注意:生产环境中如果web服务器直接处理媒体请求,中间件是捕获不到的,这个方案更适合开发环境或者媒体请求完全由Django处理的场景。
示例中间件代码
# middleware.py from django.utils.deprecation import MiddlewareMixin from .models import AuditLog from django.contrib.auth.models import AnonymousUser from django.conf import settings class MediaAuditMiddleware(MiddlewareMixin): def process_request(self, request): # 过滤媒体文件路径 if request.path.startswith(settings.MEDIA_URL): user = request.user if not isinstance(request.user, AnonymousUser) else None # 记录日志 AuditLog.objects.create( user=user, media_path=request.path, action='访问', ip_address=request.META.get('REMOTE_ADDR'), user_agent=request.META.get('HTTP_USER_AGENT', '') )
然后在settings.py的MIDDLEWARE列表里添加这个中间件:
MIDDLEWARE = [ # 其他中间件... 'your_app.middleware.MediaAuditMiddleware', ]
额外优化建议
- 异步处理日志:如果媒体访问量很大,同步记录日志可能影响请求速度,可以用Celery把日志保存操作放到异步任务中,避免阻塞请求。
- 权限控制:在视图里添加权限检查,确保只有有权限的用户才能下载对应文件(比如用
@permission_required装饰器,或者自定义权限逻辑)。 - 扩展日志字段:根据需求添加更多字段,比如访问状态(成功/失败)、文件大小等。
作为新手,先从方案一开始尝试吧,这个方法最容易理解和调试,遇到具体问题再逐步调整就好!
内容的提问来源于stack exchange,提问作者cr1
相关产品推荐
相关产品推荐

