【问题标题】:How Can I Allow Object Editing in the Django Admin For Specific Objects ONLY?如何仅允许在 Django Admin 中对特定对象进行对象编辑?
【发布时间】:2011-07-10 05:46:09
【问题描述】:

我目前正在编写一个站点,它使用django-guardian 分配整个站点使用的对象级权限。

这是所需的功能:

我希望用户有权编辑单个对象(或多个对象)。例如,如果有一个名为“Joe”的用户和一个名为“Partyline”的模型,我可能会授予“Joe”对 3 个特定“Partyline”对象的“change_partyline”的特定权限。

当 Joe 登录 Django 管理面板时,我希望他能够只编辑他的 3 个特定的“Partyline”对象,因为这些是他唯一有权编辑的东西。

这是当前的功能:

我可以将 Joe change_partyline 权限分配给 3 个 Partyline 对象——没问题。乔可以很好地登录管理面板。问题在于,由于 Joe 没有更改所有派对线路的“全局”权限,因此管理面板说他没有任何权限,并且不会让他编辑任何内容。我想找到一种方法让管理员认识到 Joe 有权编辑 3 个特定对象,并让他只查看和编辑他有权处理的那些对象。

我很想找到一种方法来完成这项工作。我现在广泛使用管理员来让我的用户管理事情,如果必须将某些功能从管理员移到网站上的其他区域,那真的会破坏演示。

如果您有任何建议,请告诉我!

作为参考,以下是一些 shell 输出,表明用户对 Partyline 对象具有 change_partyline 权限:

>>> from django.contrib.auth.models import User
>>> u = User.objects.get(id=2)
>>> from apps.partylines.models import Partyline
>>> p = Partyline.objects.get(id=3)
>>> u.has_perm('partylines.change_partyline', p)
True

这是我的 partylines.admin 模块(它显示了 Partyline 模块是如何在管理员中填充的):

from django.contrib import admin
from guardian.admin import GuardedModelAdmin
from apps.partylines.models import Partyline


class PartylineAdmin(GuardedModelAdmin):
    list_display = ('did', 'name', 'listed')
    ordering = ('did',)
    search_fields = ('did', 'name')

admin.site.register(Partyline, PartylineAdmin)

【问题讨论】:

    标签: python django django-admin django-authentication


    【解决方案1】:

    我向 Lukazs(监护人的作者)提出了类似的问题,他告诉我此功能将在未来的版本中推出(请参阅 this commitrelated issue 上的 user_can_access_owned_objects_only 属性)。如果你不愿意等待,也许你可以在 master 分支上安装源代码。

    您是否考虑过在您的模型上覆盖查询集?在我的情况下就足够了:

    # models.py
    from django.db import models
    from django.contrib.auth import models as auth_models
    
    class MagazineUser(models.Model):
        user = models.ForeignKey(auth_models.User, unique=True)
    
    class Magazine(models.Model):
        managers = models.ForeignKey(MagazineUser)
    
    # admin.py
    
    class MagazineAdmin(admin.ModelAdmin):
        def queryset(self, request):
            qs = super(admin.ModelAdmin, self).queryset(request)
    
            if request.user.is_superuser:
                return qs
    
            user_qs = MagazineUser.objects.filter(user=request.user)
            return qs.filter(managers__in=user_qs)
    

    【讨论】:

    • 这太完美了!当我问这个问题时(这是不久前),我实际上最终做了另一个解决方法,但我更喜欢你的解决方案。很高兴知道该功能最终将添加到稳定的监护人版本中:)
    • 这适用于特定的 ModelAdmin,但在其他领域当然没有意义(例如,不同模型的 ForeignKey 的选择框)。 如何完全隐藏非特权对象?
    • 找到答案:formfield_for_foreignkey
    • 请注意,在更高版本的 Django (> 1.5) 中,该方法已重命名为 get_queryset()。见stackoverflow.com/a/12354293/4293684
    【解决方案2】:

    该功能称为“行级权限”,您需要在 Django wiki here 上覆盖一些管理方法的简短说明。

    对于您的特定用例,我猜您希望 Partyline 和用户之间存在多对多关系,以便可以通过以下方式检索允许用户使用的对象:

    objects = request.user.partyline_set.all()
    

    覆盖queryset() 并返回该对象列表可能就足够了。

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 1970-01-01
      • 2011-08-31
      • 2021-05-14
      • 2013-01-29
      • 1970-01-01
      • 2015-09-24
      • 1970-01-01
      • 2019-08-21
      相关资源
      最近更新 更多