Django中隔离非当前用户创建条目的更优实现方案咨询
解决方案
方案1:抽取公共Mixin消除重复代码
你当前的重复代码问题可以通过提取通用的用户范围过滤Mixin解决,所有需要限制用户访问的视图统一继承该Mixin即可,无需每个视图重复写过滤逻辑,也能避免漏写过滤导致的安全问题。
首先定义公共Mixin:
class UserScopedMixin: # 统一添加用户过滤逻辑 def get_queryset(self): return super().get_queryset().filter(user=self.request.user) # 统一处理创建时自动绑定当前用户 def form_valid(self, form): form.instance.user = self.request.user return super().form_valid(form)
改造后的视图代码可以简化为:
class EntryListView(LockedView, UserScopedMixin, ListView): model = Entry ordering = ["-date_created"] class EntryDetailView(LockedView, UserScopedMixin, DetailView): model = Entry class EntryCreateView(LockedView, UserScopedMixin, SuccessMessageMixin, CreateView): model = Entry fields = ["title", "content"] success_url = reverse_lazy("entry-list") success_message = "Your new entry was created!" class EntryUpdateView(LockedView, UserScopedMixin, SuccessMessageMixin, UpdateView): model = Entry fields = ["title", "content"] success_message = "Your entry was updated!" def get_success_url(self): return reverse_lazy( "entry-detail", kwargs={"pk": self.object.pk} )
所有重复的get_queryset和form_valid逻辑都可以完全删掉,所有视图统一走Mixin的过滤逻辑,不会出现某一个视图漏写过滤的情况。
方案2:模型层面全局限制,从根源避免误查询
如果需要完全杜绝任何场景下(包括其他视图、脚本、后台操作)不小心查询到其他用户的条目,可以给Entry模型自定义查询集和管理器,统一收口用户过滤逻辑:
# 在你的models.py中添加如下逻辑 from django.db import models class UserEntryQuerySet(models.QuerySet): def for_user(self, user): return self.filter(user=user) class Entry(models.Model): # 你原有的字段定义保持不变 user = models.ForeignKey(to="auth.User", on_delete=models.CASCADE) title = models.CharField(max_length=255) content = models.TextField() date_created = models.DateTimeField(auto_now_add=True) # 替换默认管理器为自定义查询集的管理器 objects = UserEntryQuerySet.as_manager()
之后所有查询用户所属Entry的场景,统一调用Entry.objects.for_user(request.user)即可,不需要每次手动写filter条件,也能避免后续业务迭代时漏写过滤导致的数据泄露。如果需要更强的限制,可以重写管理器的默认查询方法,强制要求必须传入用户参数才能查询Entry数据,仅对超级用户或者后台管理场景开放全局查询权限。
安全说明
你当前基于get_queryset过滤的实现本身是安全的:Django的通用视图会优先从你重写的get_queryset中获取数据,当用户尝试访问不属于自己的条目ID时,会直接返回404错误,不会泄露其他用户的数据。使用上述方案优化后,只要保证所有操作Entry的视图都继承了对应的过滤逻辑,就不会存在安全后门。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

