Django Admin - 特定用户(管理员)内容 [英] Django Admin - Specific user (admin) content

查看:50
本文介绍了Django Admin - 特定用户(管理员)内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始组织一个新项目,假设我将有一些模型,例如 productscatalogs.

I'm starting to organize a new project and let's say i'll have a few models like products and catalogs.

我将允许我的客户(不是访客,只有特定客户)登录 Django 管理站点来创建、编辑和删除他们自己的目录.

I will allow my clients (not visitors, only specific clients) to login on Django Admin site to create, edit and delete their own catalogs.

假设我创建了一个名为 Shop" 的模型,创建每个商店(名称、地址、徽标、联系信息等)并创建一个绑定到该商店的管理员用户.

Lets say I create a model called "Shop", create every shop (name, address, logo, contact info and etc.) and create an admin user binded to that shop.

现在我希望这位新管理员(不是网站管理员,而是商店管理员——可能是用户组)查看和编辑仅与他的商店链接的目录.

Now I want this new admin (who's not a site admin, but a shop admin -- probably an user group) to see and edit only the catalogs linked with his shop.

这可能吗?

我应该在 Django Admin 中执行此操作,还是应该创建一个新的商店管理员"应用程序?

Should I do this inside the Django Admin or should I create a new "shop admin" app?

推荐答案

首先警告:Django admin 的设计理念是任何有权访问 admin 的用户 (is_staff==True)是受信任的用户,例如一名员工,因此甚至可以访问管理员的员工"称号.虽然您可以自定义管理员以限制区域,但允许组织内的任何人访问您的管理员被认为是有风险的,并且 Django 不保证此时的任何安全性.

First, the cautionary warning: The Django admin design philosophy is that any user with access to the admin (is_staff==True) is a trusted user, e.g. an employee, hence the "staff" designation to even gain access to the admin. While you can customize the admin to restrict areas, allowing anyone not within your organization access to your admin is considered risky, and Django makes no guarantees about any sort of security at that point.

现在,如果您仍想继续,您可以通过不将这些权限分配给用户来立即限制除商店以外的大多数内容.您必须授予所有店主编辑他们需要访问的任何商店模型的权限,但其他所有内容都应从他们的权限列表中删除.

Now, if you still want to proceed, you can restrict most everything but the shops right off the bat by simply not assigning those privileges to the user. You'll have to give all the shop owners rights to edit any of the shop models they'll need access to, but everything else should be left off their permissions list.

然后,对于需要仅限所有者查看的每个模型,您需要添加一个字段来存储所有者"或用户允许访问它.您可以使用 ModelAdmin 上的 save_model 方法执行此操作,该方法可以访问请求对象:

Then, for each model that needs to be limited to the owner's eyes only, you'll need to add a field to store the "owner", or user allowed access to it. You can do this with the save_model method on ModelAdmin, which has access to the request object:

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 的查询集限制为仅由当前用户拥有的那些项目:

Then you'll also need to limit the ModelAdmin's queryset to only those items own by the current user:

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 的每个易受攻击的视图以重定向,如果用户不是所有者:

However, that will only limit what gets listed, the user could still play with the URL to access other objects they don't have access to, so you'll need to override each of the ModelAdmin's vulnerable views to redirect if the user is not the owner:

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(),删除和历史观点.这很好地抽象了模型类名,使代码不那么脆弱.我也改为使用 filterexists 而不是带有 gettry...except 块.这种方式更加精简,而且实际上也产生了更简单的查询.

Thanks @christophe31 for pointing out that since the ModelAdmin's queryset is already limited by user, you can just use self.queryset() in the change, delete and history views. This nicely abstracts away the model classname making the code less fragile. I've also changed to using filter and exists instead of a try...except block with get. It's more streamlined that way, and actually results in a simpler query, as well.

这篇关于Django Admin - 特定用户(管理员)内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆