【问题标题】:Django role based views?Django基于角色的视图?
【发布时间】:2010-12-05 12:33:45
【问题描述】:

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

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

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

这是通过一些第三方应用程序完成的吗?您将如何解决这个问题?

谢谢, 皮特

【问题讨论】:

  • 各位,django 权限系统不符合我的需求。这就是我寻求架构帮助的原因:P

标签: django architecture acl


【解决方案1】:

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

http://docs.djangoproject.com/en/dev/topics/auth/

通常在您的代码中检查用户是否具有权限。用户拥有自己的权限以及他所属的组的权限。您可以从管理控制台轻松管理。

您需要查看两个部分。

  1. 检查请求页面的用户 有权这样做。
  2. 仅向用户显示链接,如果他 有权限。

对于 1. 您可以检查装饰器中的权限,如下所示:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def some_view(request):

对于2.当前登录用户的权限存储在模板变量{{ perms }}中。此代码检查与上述相同的权限。

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

要生成链接列表,您可以遍历 user.get_all_permissions() 并从字典中获取链接(或生成链接的函数):

def more_elaborate_list_of_links_for_a_perm(user):
    return ["/link1", ...]

_LINKS = {
    'polls.can_vote' : lambda u: ["/user/specific/link/" + u.id],
    'polls.can_close': lambda u: ['/static/link/1', 'static/link/2'],
    'polls.can_open' : more_elaborate_list_of_links_for_a_perm
}

def gen_links(user):
    # get_all_permissions also gets permissions for users groups
    perms = user.get_all_permissions()
    return sum((_LINKS[p](user) for p in perms if p in _LINKS), [])

可能还有很多其他方法。

【讨论】:

  • 如何生成链接列表以提供给使用 django 内置权限系统的用户?
  • 为了记录,我没有选择这个答案作为最佳答案。我不认为是。
【解决方案2】:

我们遇到了类似的问题。 Django 的组并不真正适合这个,但你可以硬塞进去。

我们的做法是这样的:

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

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

如果您的系统需要,您可以保留单独的 ManyToMany 负权限,或单独的读/写权限。您还可以定义一组元组(医生、护士),让您的查找过滤器检索权限的实际子集。

就您的链接栏问题而言,您可以使用相同的系统以编程方式生成它们 - 根据用户可以查看或编辑的对象类别进行过滤,然后使用 get_absolute_url() 类型函数(也许称之为get_index_url()) 返回每类对象索引的链接。

因为这一切都相当复杂,您可能最终希望对这些内容进行某种程度的缓存,但在您进行优化之前先让它工作。这是可能的,而且代码比文字更丑。

【讨论】:

  • 我最终使用我们的应用程序走这条路,但它并不理想。我发现性能下降了一点。我正在其他地方寻找更好的 ACL 解决方案
  • 这根本不可扩展。关于 ACL 的任何想法?
【解决方案3】:

有一个关于 Django 中基于角色的权限的新的非常有趣的项目: http://bitbucket.org/nabucosound/django-rbac

【讨论】:

    【解决方案4】:

    不久前我遇到了类似的问题。我们的解决方案成功了,尽管它可能对您的情况来说太简单了。就像大家建议的那样,我们使用 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 User 模型的用户配置文件。它所包含的只是一个链接到上述 Group 模型的 ManyToManyField。这使我们能够根据需要向用户授予对零个或多个组的访问权限。 (documentation)

    class UserProfile( models.Model ):
        user = models.ForeignKey( User, unique=True )
        groups = models.ManyToManyField( Group )
        ...
    

    这为我们提供了两全其美的优势,并避免了我们试图将所有内容硬塞到 django 的权限系统中。我正在使用这个基本设置来控制用户对体育内容的访问(有些用户可以访问整个联赛,有些只能访问一两个会议,有些只能访问个别球队),并且在这种情况下效果很好。它可能足以满足您的需求。

    【讨论】:

      【解决方案5】:

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

      from django.contrib.auth.models import Permission
      perms = Permission.objects.all()
      

      有一个API for other authentication and authorization sources,所以你不需要坚持这个权限表。

      你可以破解这个 Django 系统来满足你在这个授权模型 (RBAC) 方面的需求,或者你可以想出一个类似 ACL 的解决方案。

      【讨论】:

      • 每个对象 acl 的任何提示?
      【解决方案6】:

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

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

      基本上,这是一种奇怪的 ACL 系统。创建机制并不难。所有的魔法都在于确定在什么情况下哪些令牌进入存储桶。

      【讨论】:

        【解决方案7】:

        您可以使用 django 用户角色

        https://github.com/dabapps/django-user-roles

        【讨论】:

          【解决方案8】:

          此问题已在 2009 年 10 月提出,问题在 2012 年 7 月仍然存在。

          我搜索了一个很好的基于角色的应用,发现django-permission是最好的结果。

          我需要的三个重要功能是角色、视图装饰器模板标签;显然django-permissions 拥有所有这些。请阅读 docs 了解它的用法。

          唯一的缺点是它正在开发中。

          【讨论】:

            【解决方案9】:

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

            视图函数被修饰:

            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 属性中 设置在上下文处理器中。经过身份验证的用户获得了一个角色,对于未洗过的大众 一个虚拟角色。

            在模板内进一步限制了对信息的访问:

             {% if not request.role.can.view_all_products %}
                      Lots of products, yeah!
             {% endif %}
            

            在我看来不是最干净的解决方案,但按预期工作。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-03-15
              • 2021-05-06
              • 2014-04-28
              • 1970-01-01
              • 1970-01-01
              • 2014-02-16
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多