如何在Django Admin中仅为特定对象允许编辑?
我现在正在写一个网站,使用django-guardian来为网站中的对象分配权限。
我想要的功能是:
我希望用户能够编辑单个对象(或者多个对象)。比如说,有一个用户叫“Joe”,还有一个模型叫“Partyline”,我可以给“Joe”特定的权限,让他可以“更改Partyline”这3个特定的“Partyline”对象。
当Joe登录到Django的管理面板时,我希望他只能编辑这3个特定的“Partyline”对象,因为这些是他有权限编辑的唯一对象。
现在的功能是:
我可以给Joe这3个Partyline对象分配更改权限,这没问题。Joe也可以顺利登录到管理面板。但问题是,由于Joe没有“全局”权限去更改所有的Partyline,管理面板就显示他没有任何权限,因此不让他编辑任何东西。我想找到一种方法,让管理面板能识别出Joe只对这3个特定对象有编辑权限,并只让他查看和编辑这些他可以操作的对象。
我非常希望能找到解决这个问题的方法。我现在广泛使用管理面板来让用户管理内容,如果某些功能必须移到网站的其他地方,那样会影响用户体验。
如果你有任何建议,请告诉我!
作为参考,这里有一些命令行输出,显示用户对一个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 个回答
这个功能叫做“行级权限”,在Django的维基页面上有一些你需要重写的管理员方法的简单解释。
针对你的具体需求,我猜你想在Partyline和User之间建立一个多对多的关系,这样就可以通过以下方式获取用户可以访问的对象:
objects = request.user.partyline_set.all()
可能只需要重写一下queryset()
方法,返回那个对象列表就可以了。
我之前问过Lukazs(guardian的作者)类似的问题,他告诉我这个功能会在未来的版本中推出(可以查看一下这个提交中的user_can_access_owned_objects_only属性,以及相关问题)。如果你不想等的话,可以考虑直接在主分支上安装源代码。
你有没有想过在你的模型上重写查询集(queryset)?对我来说,这样做就足够了:
# 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)