Django基于角色的视图?

Django基于角色的视图?,django,architecture,acl,Django,Architecture,Acl,我正在寻找一些关于其他人将如何构建此架构的信息。我将提供基于类(django组)的视图 例如,用户的组将确定他或她将有权访问哪些视图/模板。我正在考虑在表中存储查看函数的路径,以确定用户的链接栏将包含哪些内容。还可以存储筛选器规范,以确定哪些行将填充这些模板 一个很好的例子是医院护理单位。一个单位的护士不需要看整个医院的病人。他们只需要看他们的病人。同一单位的医生也只需要看这些病人,但他们应该有更大的功能 这是通过第三方应用程序完成的吗?你会如何处理这个问题 谢谢, PeteDjango已经有了

我正在寻找一些关于其他人将如何构建此架构的信息。我将提供基于类(django组)的视图

例如,用户的组将确定他或她将有权访问哪些视图/模板。我正在考虑在表中存储查看函数的路径,以确定用户的链接栏将包含哪些内容。还可以存储筛选器规范,以确定哪些行将填充这些模板

一个很好的例子是医院护理单位。一个单位的护士不需要看整个医院的病人。他们只需要看他们的病人。同一单位的医生也只需要看这些病人,但他们应该有更大的功能

这是通过第三方应用程序完成的吗?你会如何处理这个问题

谢谢,
Pete

Django已经有了一个组和权限系统,这可能足以满足您的需要

通常在代码中检查用户是否具有权限。用户拥有自己的权限以及所属组的权限。您可以很容易地从管理控制台进行管理

你需要看两个部分

  • 检查是否有用户请求页面 有权这样做
  • 仅显示指向用户的链接,如果用户 有许可证
  • 1。您可以在装饰器中检查权限,如下所示:

    from django.contrib.auth.decorators import permission_required
    
    @permission_required('polls.can_vote')
    def some_view(request):
    
    两个人。当前登录用户的权限存储在模板变量{{perms}中。此代码检查与上面相同的权限

    {% if perms.polls.can_vote %}
        <a href="/vote">vote</a>
    {% endif %}
    

    可能还有很多其他方法。

    如果不需要真正的每对象ACL,那么可以使用Django权限系统。要获取所有可用权限的列表,请执行以下操作:

    from django.contrib.auth.models import Permission
    perms = Permission.objects.all()
    
    存在一个权限表,因此您不需要坚持使用此权限表


    您可以破解此Django系统以满足您在此授权模型(RBAC)方面的需求,或者您可以提出类似ACL的解决方案。

    我们也遇到了类似的问题。Django的团队并不适合这样做,但你可以把他们塞进

    我们的做法如下:

    每个访问控制对象都与groups表有许多关系。每个组用于定义特定类型的权限(“可以查看患者基本信息”、“可以编辑患者联系信息”等)。用户将被添加到他们应有权限的组中(在您只查看该医院的患者的示例中,您可以有一个“valley view医院”组)

    然后,当您向用户显示记录列表时,将根据两个组的组合进行筛选。用户必须具有所有关联的组权限才能查看给定对象

    如果您的系统需要,您可以单独保留许多负面权限或单独的读/写权限。您还可以定义一组元组(医生、护士),这些元组会导致查找筛选器检索实际的权限子集

    至于你的链接栏问题,你可以使用相同的系统过滤器,根据用户可以看到或编辑的对象类别,通过编程生成这些链接,然后使用
    get_absolute_url()
    type函数(可以称之为
    get_index_url()
    )返回每个对象类别的索引链接


    因为所有这些都相当复杂,所以您可能最终想要对这些东西进行某种程度的缓存,但在您进行优化之前先让它工作起来。这是可能的,而且它在代码上没有在文字上那么难看。

    不久前我也遇到过类似的问题。我们的解决方案成功了,尽管对于您的情况来说可能太简单了。正如大家所建议的,我们使用django权限系统来控制用户与模型的交互。然而,我们不仅尝试对用户进行分组,还通过GenericForeignKey对对象进行分组

    我们构建了一个模型,该模型与自身相链接,以允许开发层次结构

    class Group( models.Model ):
        name = models.CharField( ... )
        parent = models.ForeignKey( 'self', blank=True, null=True)
        content_type = models.ForeignKey( ContentType )
        object_id = models.PositiveIntegerField()
        content_object = generic.GenericForeignKey( 'content_type', 'object_id' )
        ...
    
    为了使其工作,我们还创建了一个模型作为django用户模型的用户配置文件。它所包含的只是一个与上面的集团模型相关联的许多领域。这允许我们根据需要为用户提供零个或多个组的访问权限。()


    这给了我们两全其美的东西,也避免了我们试图把一切都塞进django的许可系统。我使用这个基本设置来控制用户对体育内容的访问(有些用户可以访问整个联赛,有些用户只能访问一到两个会议,有些用户只能访问单个球队),在这种情况下,它工作得很好。这可能是一个足够通用的方法,以满足您的需要。

    在一个为黑比诺葡萄酒专家创建的网站上,我们基于许多不同的标准创建了每个对象访问。如果入站链接有一个与特色酒庄域名匹配的referer字段,那么用户将获得一个“酒庄令牌”,该令牌扩展到与该酒庄相关的所有文章、品尝笔记等。我们在品尝活动中使用“命名代币”作为赠品,他们允许访问网站的特定部分。我们甚至使用它来授予搜索引擎蜘蛛某些类型的权限,然后确保来自这些搜索引擎的链接具有与蜘蛛相同的权限(即没有伪装游戏)

    简短的版本是,您可以创建一个类(我们称之为TokenBucket,其中包含令牌),每个对象(在详细信息页面、列表页面或其他任何页面上)都可以询问用户的TokenBucket是否允许特定级别的访问


    基本上这是一种奇怪的ACL系统。创造机械师并不难。所有的魔力在于确定在什么情况下哪些代币进入桶中。

    我们使用了一个角色库系统来解决类似的问题。 基本上,用户拥有承担不同角色的权限

    视图功能得到了修饰:

    def needs_capability(capability,redirect_to="/cms/"):
       def view_func_wrapper(view_func):
           def wrapped_view_func(request,*args,**kwargs):
               if not request.role._can(capability):
                  return HttpResponseRedirect(redirect_to)
               return view_func(request,*args,**kwargs)
           return wrapped_view_func
       return view_func_wrapper
    
    其余的魔法在
    request.role
    属性中,该属性 设置在上下文处理器中。认证
    class UserProfile( models.Model ):
        user = models.ForeignKey( User, unique=True )
        groups = models.ManyToManyField( Group )
        ...
    
    def needs_capability(capability,redirect_to="/cms/"):
       def view_func_wrapper(view_func):
           def wrapped_view_func(request,*args,**kwargs):
               if not request.role._can(capability):
                  return HttpResponseRedirect(redirect_to)
               return view_func(request,*args,**kwargs)
           return wrapped_view_func
       return view_func_wrapper
    
     {% if not request.role.can.view_all_products %}
              Lots of products, yeah!
     {% endif %}