Django如何通过admin后台向指定用户发文件且用户仅可见自身内容
Django管理员分配员工专属工作文件实现方案
1. 定义数据模型
先在你的业务app的models.py中新增专属工作文件表,直接关联系统用户模型,从数据层面绑定文件和所属员工的对应关系:
from django.db import models from django.contrib.auth import get_user_model from django.utils import timezone # 兼容自定义用户模型 User = get_user_model() class EmployeeWorkFile(models.Model): assigned_employee = models.ForeignKey( User, on_delete=models.CASCADE, related_name="work_files", verbose_name="所属员工" ) work_file = models.FileField(upload_to="employee_work/%Y/%m/", verbose_name="工作文件") file_name = models.CharField(max_length=255, verbose_name="文件名称") admin_remark = models.TextField(blank=True, null=True, verbose_name="管理员备注") create_time = models.DateTimeField(default=timezone.now, verbose_name="分配时间") is_viewed = models.BooleanField(default=False, verbose_name="是否已查看") class Meta: verbose_name = "员工工作文件" verbose_name_plural = "员工工作文件" # 新增管理员专属分配权限 permissions = [("can_assign_workfile", "可分配员工工作文件")] def __str__(self): return f"{self.assigned_employee.username}-{self.file_name}"
模型写完后执行python manage.py makemigrations和python manage.py migrate完成数据表创建。
2. 配置Admin后台分配入口
在对应app的admin.py中注册模型,限制只有管理员/有分配权限的账号可以操作文件分配,直接复用Django Admin自带的表单、上传能力,不需要额外开发分配页面:
from django.contrib import admin from .models import EmployeeWorkFile @admin.register(EmployeeWorkFile) class WorkFileAdmin(admin.ModelAdmin): list_display = ["file_name", "assigned_employee", "create_time", "is_viewed"] list_filter = ["assigned_employee", "create_time"] search_fields = ["file_name", "assigned_employee__username"] # 权限控制:仅管理员/有分配权限的用户可见该模块 def has_module_permission(self, request): return request.user.is_superuser or request.user.has_perm("你的app名.can_assign_workfile") def has_add_permission(self, request): return self.has_module_permission(request) def has_change_permission(self, request, obj=None): return self.has_module_permission(request) def has_delete_permission(self, request, obj=None): return self.has_module_permission(request)
配置完成后,管理员登录后台即可选择对应员工、上传文件完成分配。
3. 员工端视图与权限控制
这部分是防越权的核心,所有涉及工作文件的查询、下载操作,必须强制过滤当前登录用户,绝对不能直接通过文件ID查询不校验所属关系。
个人资料页视图
from django.shortcuts import render from django.contrib.auth.decorators import login_required from .models import EmployeeWorkFile @login_required def profile(request): # 仅查询当前登录用户自己的文件 user_files = EmployeeWorkFile.objects.filter(assigned_employee=request.user).order_by("-create_time") # 标记未读文件为已查看 user_files.filter(is_viewed=False).update(is_viewed=True) return render(request, "employee/profile.html", {"user_files": user_files})
带权限校验的文件下载视图
不要直接暴露媒体文件的直链,避免被人猜解URL越权下载,所有下载请求先走权限校验:
from django.http import Http404, FileResponse from django.contrib.auth.decorators import login_required import os @login_required def file_download(request, fid): # 查询时直接绑定当前用户,不存在直接返回404 try: target_file = EmployeeWorkFile.objects.get(id=fid, assigned_employee=request.user) except EmployeeWorkFile.DoesNotExist: raise Http404("无访问权限") # 返回文件流 fp = target_file.work_file.open("rb") response = FileResponse( fp, as_attachment=True, filename=os.path.basename(target_file.work_file.name) ) return response
写完视图后在urls.py中配置对应路由即可。生产环境可以配合Nginx的X-Accel-Redirect做文件转发,提升下载性能,权限校验逻辑保持不变。
4. 个人资料页模板渲染
在员工个人资料模板中遍历传入的文件列表,渲染下载入口即可:
<div class="work-file-section"> <h3>分配给我的工作文件</h3> {% if user_files %} <ul class="file-list"> {% for f in user_files %} <li> <p class="file-name">{{ f.file_name }}</p> <p class="file-meta">分配时间:{{ f.create_time|date:"Y-m-d H:i" }}</p> {% if f.admin_remark %}<p class="remark">管理员备注:{{ f.admin_remark }}</p>{% endif %} <a href="{% url 'file_download' f.id %}" class="download-btn">下载文件</a> </li> {% endfor %} </ul> {% else %} <p>暂无分配的工作文件</p> {% endif %} </div>
核心注意事项
- 任何涉及工作文件的数据库查询,都不能省略
assigned_employee=request.user的过滤条件,这是防止水平越权的核心 - 不要给普通员工开放Admin后台的工作文件模块权限,所有员工侧操作都走前台页面
- 如果后续要做文件删除、预览等功能,同样要在查询时校验文件所属用户和当前登录用户一致
内容的提问来源于stack exchange,提问作者alphies pro
相关产品推荐
相关产品推荐

