如何仅在Django Admin中为特定对象允许对象编辑?

时间:2011-03-07 09:46:42

标签: python django django-admin django-authentication

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

以下是所需的功能:

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

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

以下是当前功能:

我可以将Joe change_partyline权限分配给3个Partyline对象 - 没问题。 Joe可以很好地登录管理面板。问题是,由于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)

2 个答案:

答案 0 :(得分:4)

我向Lukazs(监护人的作者)提出了类似的问题,他告诉我这个功能将在未来版本中发布(请参阅this commit上的user_can_access_owned_objects_only属性和related issue)。如果您不愿意等待,也许您可​​以在主分支上安装源代码。

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

# 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)

答案 1 :(得分:2)

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

对于您的特定用例,我猜您需要Partyline和User之间的ManyToMany关系,以便可以通过以下方式检索用户允许的对象:

objects = request.user.partyline_set.all()

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