You need to enable JavaScript to run this app. Django如何实现仅允许物品所有者对其执行编辑、删除操作
优惠活动
大模型
产品
解决方案
定价
更多

Django如何实现仅允许物品所有者对其执行编辑、删除操作

实现对象级编辑/删除权限的落地方法

现有代码的权限缺陷

  • SiteUpdate仅通过LoginRequiredMixin完成了“是否登录”的基础校验,未对“当前登录用户是否为待操作对象的所有者”做判断,所有登录用户拿到编辑链接即可修改任意Item
  • SiteDelete未配置任何登录校验,未登录用户只要拿到正确的删除链接即可直接删除记录

具体改造方案

借助Django内置的UserPassesTestMixin即可快速实现对象级权限控制,不需要重复造轮子:

  1. 导入所需的权限组件
    在views.py顶部引入两个权限校验Mixin:
    from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
    
  2. 重写编辑、删除视图的校验逻辑
    给两个目标视图同时叠加两个权限Mixin,通过test_func方法定义权限判断规则:
    class SiteList(ListView):
        model = Items
    
    
    class SiteUpdate(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
        model = Items
        form_class = SiteUpdateForm
        success_url = reverse_lazy('portfolio:sitelist')
    
        def test_func(self):
            # 取当前待编辑的Item实例
            item = self.get_object()
            # 权限规则:超管可操作所有记录,普通用户仅可操作自己创建的记录
            return self.request.user.is_superuser or item.author == self.request.user
    
    
    class SiteDelete(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
        model = Items
        success_url = reverse_lazy('portfolio:sitelist')
    
        def test_func(self):
            # 和编辑权限规则完全对齐
            item = self.get_object()
            return self.request.user.is_superuser or item.author == self.request.user
    

必须注意的细节

  • 继承顺序不能出错:一定要把LoginRequiredMixin、UserPassesTestMixin放在继承列表的最左侧。Django类视图遵循从左到右的方法执行顺序,先校验登录状态,再做对象权限判断,避免未登录时读取用户属性触发空指针错误。
  • 当test_func校验不通过时,Django会自动返回403权限拒绝响应,直接拦截非法操作,不需要手写额外的跳转逻辑。
  • 建议后续优化Items模型的author字段:去掉字段配置里的null=True,在新增Item的视图里自动绑定当前登录用户为作者,否则没有绑定作者的历史数据,除超管外所有普通用户都无法通过权限校验。自动绑定作者的实现可在新增视图的方法中添加:
    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)
    

内容的提问来源于stack exchange,提问作者illyria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 00:27:06