首先,警告性警告:Django 管理员设计理念是任何有权访问管理员 (is_staff==True) 的用户都是受信任的 用户,例如一名员工,因此甚至可以访问管理员的“员工”称号。虽然您可以自定义管理员以限制区域,但允许您组织内的任何人访问您的管理员被认为是有风险的,并且 Django 在这一点上不保证任何类型的安全性。
现在,如果您仍想继续,您可以通过不将这些权限分配给用户来立即限制除商店以外的大多数内容。您必须授予所有店主编辑他们需要访问的任何商店模型的权限,但其他所有内容都应从他们的权限列表中删除。
然后,对于需要仅限所有者查看的每个模型,您需要添加一个字段来存储“所有者”或用户允许访问它。您可以使用ModelAdmin 上的save_model 方法来执行此操作,该方法可以访问请求对象:
class MyModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user
super(MyModelAdmin, self).save_model(request, obj, form, change)
然后您还需要将 ModelAdmin 的查询集限制为仅由当前用户拥有的那些项目:
class MyModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(MyModelAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)
但是,这只会限制列出的内容,用户仍然可以使用 URL 来访问他们无权访问的其他对象,因此您需要覆盖 ModelAdmin 的每个易受攻击的视图以重定向,如果用户不是所有者:
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
class MyModelAdmin(admin.ModelAdmin):
def change_view(self, request, object_id, form_url='', extra_context=None):
if not self.queryset(request).filter(id=object_id).exists():
return HttpResponseRedirect(reverse('admin:myapp_mymodel_changelist'))
return super(MyModelAdmin, self).change_view(request, object_id, form_url, extra_context)
def delete_view(self, request, object_id, extra_context=None):
if not self.queryset(request).filter(id=object_id).exists():
return HttpResponseRedirect(reverse('admin:myapp_mymodel_changelist'))
return super(MyModelAdmin, self).delete_view(request, object_id, extra_context)
def history_view(self, request, object_id, extra_context=None):
if not self.queryset(request).filter(id=object_id).exists():
return HttpResponseRedirect(reverse('admin:myapp_mymodel_changelist'))
return super(MyModelAdmin, self).history_view(request, object_id, extra_context)
2012 年 6 月 5 日更新
感谢@christophe31 指出由于ModelAdmin 的查询集已经受到用户的限制,您可以在更改、删除和历史视图中使用self.queryset()。这很好地抽象了模型类名,使代码不那么脆弱。我也改为使用filter 和exists,而不是try...except 块get。这种方式更加精简,而且实际上也产生了更简单的查询。