Django管理员中的对象级权限

Ami*_*tad 6 python django django-models django-guardian

我有一个看起来像这样的模型:

class Change(models.Model):
    RFC = models.CharField(max_length=10)
    Ticket_Number = models.CharField(max_length=10)
    Plan_Owner = models.ForeignKey(User)
Run Code Online (Sandbox Code Playgroud)

然后我通过这个在Django管理员中注册模型:

class ChangeAdmin(admin.ModelAdmin):
    search_fields = ('RFC', 'Ticket_Number','Plan_Owner')
    list_display = ('RFC', 'Ticket_Number','Plan_Owner')

    fieldsets = [
        ('Ticket Details', {
            'fields': ['RFC', 'Ticket_Number', 'Plan_Owner']}),
    ]

admin.site.register(Change, ChangeAdmin)
Run Code Online (Sandbox Code Playgroud)

我想要实现的是确保特定更改的Plan_owner是唯一可以在超级用户之外编辑它的人.每个人都可以查看它,但计划所有者是唯一可以对其进行更改的人.另外,通过编辑,我的意思是,他可以做任何事情,但删除一行.我已经看过Django监护人,它完全符合我的要求但是必须手动为每一行设置监护人的权限.我正在寻找一个解决方案,其中这些权限是根据我的要求自动设置的...

Kus*_*era 8

您可以通过覆盖ModelAdmin类的get_queryset()轻松完成此操作。所以get_queryset()是查询要在管理站点中显示的所有对象的地方。例如,如果您返回get_queryset (),将在管理站点中显示模型中的所有对象。如果您返回get_queryset (),将不会在管理站点中的模型中显示任何值。Change.objects.all()ChangeChange.objects.none()Change

\n

这是文档提到的有关get_queryset()的内容。

\n
\n

返回将用于检索此视图将显示的对象的查询集。默认情况下,get_queryset() 返回queryset属性的值(如果已设置),否则它通过调用模型属性 \xe2\x80\x99s 默认管理器上的 all() 方法来构造QuerySet 。

\n
\n

我只是在你的类中重写get_queryset()ChangeAdmin

\n
class ChangeAdmin(admin.ModelAdmin):\n    model = Change\n    search_fields = (\'RFC\', \'Ticket_Number\',\'Plan_Owner\')\n    list_display = (\'RFC\', \'Ticket_Number\',\'Plan_Owner\')\n\n        fieldsets = [\n        (\n            \'Ticket Details\', {\n                \'fields\': [\'RFC\', \'Ticket_Number\', \'Plan_Owner\']\n            }\n        ),\n    ]\n\n    def get_queryset(self, request):\n        if request.user.is_superuser:\n            return Change.objects.all()\n        \n        try:\n            return Change.objects.filter(plan_owner_id=request.user.id)\n        except:\n            return Change.objects.none()\n\n\nadmin.site.register(Change, ChangeAdmin)\n
Run Code Online (Sandbox Code Playgroud)\n

根据此示例,如果超级用户登录到管理站点,他们将看到模型中的所有对象Change。如果表中的其他用户Change将显示他们自己的对象(因为在本例中,它是根据模型进行过滤的Plan_OwnerChange,否则管理站点中不会显示任何内容。

\n


Ser*_*eim 6

我不会使用对象级权限来处理与您的要求一样简单的事情.你只需要有一个ownerForeignKey的到模型中,只允许每个对象的所有者对其进行修改(您可以使用Plan_Owner- 请改为plan_ownerTicket_Numberticket_number能与PEP 8兼容 Django的风格指南).

我写了一篇文章,描述了如何在django中执行此操作:

http://spapas.github.io/2013/11/05/django-authoritiy-data/

实际上我正在描述如何使用用户所属的权限,每个用户都可以编辑他的权限对象,但您的要求已涵盖.

更新

为了完整起见,我在这里添加了实现:

您的创建和更新基于类的视图必须将请求传递给您的表单,您的详细信息和更新CBV应该只允许获取属于该用户的对象(假设您的模型已命名UserData:

class UserDataCreateView(CreateView):
  model=models.UserData

  def get_form_kwargs(self):
      kwargs = super(UserDataCreateView, self).get_form_kwargs()
      kwargs.update({'request': self.request})
      return kwargs

class UserDataDetailView(DetailView):
  def get_object(self, queryset=None):
      obj = super(UserDataDetailView, self).get_object(queryset)
      if not user_has_access(obj, self.request):
          raise Http404(u"Access Denied")
      return obj

class UserDataUpdateView(UpdateView):
  model=models.AuthorityData

  def get_form_kwargs(self):
      kwargs = super(UserDataUpdateView, self).get_form_kwargs()
      kwargs.update({'request': self.request})
      return kwargs

  def get_object(self, queryset=None):
      obj = super(UserDataUpdateView, self).get_object(queryset)
      if not user_has_access(obj, self.request):
          raise Http404(u"Access Denied")
      return obj
Run Code Online (Sandbox Code Playgroud)

它检查是否request.user具有权限(是对象的所有者)并且还将其传递requestModelForm.has_access上面定义的函数只检查当前用户是否是对象的所有者:

def has_access(obj, req):
    if req.user == obj.owner:
        return True
    return False
Run Code Online (Sandbox Code Playgroud)

Yot ModelForm应该是这样的(创建/更新相同):

class UserDataModelForm(forms.ModelForm):
    class Meta:
      model = models.UserData
      exclude = ('owner',)

    def __init__(self, *args, **kwargs):
      self.request = kwargs.pop('request', None)
      super(ActionModelForm, self).__init__(*args, **kwargs)

    def save(self, force_insert=False, force_update=False, commit=True):
      obj = super(UserDataModelForm, self).save(commit=False)
      if obj:
          obj.owner = self.request.user
          obj.save()
      return obj
Run Code Online (Sandbox Code Playgroud)

它消除了requestkwargs并将其设置作为一个属性,并在将其保存设置对象的所有者reqest.user.