You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:03:09