Django Admin - 具体用户(admin)内容 [英] Django Admin - Specific user (admin) content

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

问题描述

我开始组织一个新项目,假设我有几个模型,如产品目录

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管理员还是应该创建一个新的店铺管理应用程序?

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

推荐答案

首先,警告警告:Django管理员的设计理念是任何具有访问权限的用户( i s_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.

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

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 queryset(self, request):
        qs = super(MyModelAdmin, self).queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(owner=request.user)

,这只会限制列出的内容,用户仍然可以使用URL访问他们无法访问的其他对象,因此您需要覆盖每个t如果用户不是所有者,他的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)

更新06/05/12

感谢@ christophe31指出,由于 ModelAdmin 的查询器已被用户限制,您可以在更改,删除和历史记录视图中使用 self.queryset()。这很好地抽象出了模型类名,使得代码更不脆弱。我也改为使用过滤器存在而不是 try ... 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 - 具体用户(admin)内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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