【问题标题】:How to check (in template) if user belongs to a group如何检查(在模板中)用户是否属于某个组
【发布时间】:2016-04-06 22:16:36
【问题描述】:

如何在模板中检查用户是否属于某个组?

在生成templateview 中是可能的,但是如果我想在扩展模板的base.html 中检查它怎么办(它没有自己的视图功能)?

我所有的模板都扩展了base.html,因此在每个view 中检查它并不好。

base.html 包含上栏,其中应包含按钮,具体取决于group 登录用户所在的位置(客户、卖家)。

在我的base.html 中是:

{% if user.is_authenticated %}

这还不够,因为我必须对来自Customers 的用户和来自Sellers 的用户采取不同的行动。

所以我想要的是:

{% if user.in_group('Customers') %}
 <p>Customer</p>
{% endif %}
{% if user.in_group('Sellers') %}
<p>Seller</p>
{% endif %}

【问题讨论】:

    标签: python django django-admin django-permissions


    【解决方案1】:

    就我而言,问题是,我使用的是{% load filter_method_name %}

    我不得不改成{% load filename %}

    例如,

    app/
        __init__.py
        models.py
        templatetags/
            __init__.py
            auth_extras.py
        views.py
    

    这里,模板 taq 将是 {% load auth_extras %}

    然后我不得不重新启动服务器。

    【讨论】:

      【解决方案2】:

      首先你需要在has_group.py内部定义一个自定义过滤函数

      from django import template
      from xx.models import Xuser
      
      
      register = template.Library()
      
      
      @register.filter(name='has_group')
      def has_group(user, group_name):
          try:
              group = Xuser.objects.get(email=user.email)
              if group.role == group_name:
                  return True
              else:
                  return False
          except Xuser.DoesNotExist:
              return False
      
          return group
      
       
      

      django settings.py文件中你需要添加

       'libraries': {
                      'my_templatetag': 'xx.templates.has_group',
      
                  },
      

      TEMPLATES = []

      然后添加

      {% load my_templatetag %}
      

      在您的 example.html 中

      最后

      {% if user|has_group:"admin" %} 
       {% endif %}
      

      【讨论】:

        【解决方案3】:

        你可以用这个:

        {% for group_for in request.user.groups.all %}
            {% if group_for.name == 'Customers' %}
                Text showed to users in group 'Customers'
            {% elif group_for.name == 'Sellers' %}
                Text showed to users in group 'Sellers'
            {% endif %}
        {% endfor %}
        

        这是遍历与发出请求的用户相关的组,如果迭代组的名称等于“客户”、“卖家”等,则打印文本

        【讨论】:

          【解决方案4】:

          您需要自定义模板标签:

          from django import template
          
          register = template.Library() 
          
          @register.filter(name='has_group') 
          def has_group(user, group_name):
              return user.groups.filter(name=group_name).exists() 
          

          在您的模板中:

          {% if request.user|has_group:"mygroup" %} 
              <p>User belongs to my group 
          {% else %}
              <p>User doesn't belong to mygroup</p>
          {% endif %}
          

          来源:http://www.abidibo.net/blog/2014/05/22/check-if-user-belongs-group-django-templates/

          文档:https://docs.djangoproject.com/en/dev/howto/custom-template-tags/

          【讨论】:

          • 杂烩,谢谢。我已经阅读了那个网页,但我不知道这段代码应该在哪里。
          • 你会如何处理Group.objects.get(name=group_name) 不返回对象的情况?
          • @danielmaxx 你可以通过Group.objects.filter(name=group_name).exists()得到一个布尔值
          • 为了避免多次查询,我建议使用return user.groups.filter(name=group_name).exists()
          • 您忘记了 html 模板中的 {% load has_group %}
          【解决方案5】:

          我发现最简单的方法是使用 context_preprocessor 将所有组名称添加到上下文中

          在您的应用中创建一个文件context_processors.py 并添加以下内容:

          def user_groups_processor(request):
              groups = []
              user = request.user
              if user.is_authenticated:
                  groups = list(user.groups.values_list('name',flat = True))
              return {'groups': groups}
          
          

          在您的设置中,添加新的上下文处理器

          TEMPLATES = [
              {
                  'BACKEND': 'django.template.backends.django.DjangoTemplates',
                  'DIRS': [],
                  'APP_DIRS': True,
                  'OPTIONS': {
                      # ... some options here ...
                       "context_processors": [
                          "my_app.context_processors.user_groups_processor"
                      ],
                  },
              },
          ]
          

          或者如果你喜欢settings.py

          TEMPLATES[0]['OPTIONS']['context_processors'].append("my_app.context_processors.user_groups_processor")
          

          之后,您可以在模板中使用:

          {% if 'vip' in groups %}
            <p>Paragraph only visible to VIPs</p>
          {% endif %}
          

          【讨论】:

          • 这对我来说是最好的答案。我之前做过自定义过滤器来获取当前用户组,但每次在模板中使用标签时都会发出数据库请求。对于某些模板,我需要在模板的很多地方检查角色,导致许多DB请求,以获得相同的信息。上下文处理器更适合我的需求。
          【解决方案6】:

          我会说最好的方法是:

          yourapp/templatetags/templatetagname.py

          from django import template
          
          register = template.Library()
          
          @register.filter(name='has_group')
          def has_group(user, group_name):
              return user.groups.filter(name=group_name).exists()
          

          yourapp/templates/yourapp/yourtemplate.html:

          {% load has_group %}
          
          {% if request.user|has_group:"mygroup" %} 
              <p>User belongs to my group</p>
          {% else %}
              <p>User does not belong to my group</p>
          {% endif %}
          

          编辑:按照 cmets 中的建议添加了带有模板标签加载的行。

          EDIT2:修正了小错字。

          【讨论】:

          • 值得一提的是,您需要在要使用它的每个 HTML 模板的顶部包含 {% load templatetagname %}。
          • @pawisonon 这就是问题所在,也是我不使用它的原因。因为我有 10 个模板,以后可能会做更多。
          【解决方案7】:

          虽然mishbah给出的答案是正确的,但它对我不起作用。

          我正在使用 Django 2.2.7,我发现应该将 register = template.Library() 替换为 from django.template.defaultfilters import register

          我希望有人会觉得它有用。

          【讨论】:

            【解决方案8】:
            {% if target_group in user.groups.all.0.name %}
                # do your stuff
            {% endif %}
            

            【讨论】:

            • 你能解释一下你的答案吗?
            • 即使用户属于多个组,这种方法也有效。所以它只是检查特定组(target_group)是否在用户组中。注意:target_group 是组名,不是 Group 对象!
            • 您的答案只检查第一项,因为您使用的是索引0。如果您想在模板中执行此操作,最好循环访问相关的组对象,然后匹配 name 属性。 {% for group in user.groups.all %} {%if group.name == target_group %} Do smthg {%endif%} {%endfor%}
            • @Codebender 但是如果你有 2 个组,你不能让 if group.name == target_group1 and group.name == target_group2 它总是返回 False,即使用户同时拥有这两个组,因为 for 循环一次检查一个。
            【解决方案9】:

            在您的应用程序中创建一个文件夹“templatetags”。在此文件夹中创建两个文件:

            __init__.py

            auth_extras.py

            from django import template
            from django.contrib.auth.models import Group 
            
            register = template.Library()
            
            @register.filter(name='has_group')
            def has_group(user, group_name): 
                group = Group.objects.get(name=group_name) 
                return True if group in user.groups.all() else False
            

            现在应该是这样的:

            app/
                __init__.py
                models.py
                templatetags/
                    __init__.py
                    auth_extras.py
                views.py
            

            添加模板标签模块后,您需要重启服务器才能使用模板中的标签或过滤器。

            在您的 base.html(模板)中使用以下内容:

            {% load auth_extras %}
            

            并检查用户是否在组“主持人”中:

            {% if request.user|has_group:"moderator" %} 
                <p>moderator</p> 
            {% endif %}
            

            文档:https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/

            【讨论】:

            • 你可以通过将它添加到项目文件夹中来将它用于所有应用程序吗?
            【解决方案10】:

            请注意,如果数据库中不存在该组,则会出现异常。

            自定义模板标签应为:

            from django import template
            from django.contrib.auth.models import Group
            
            register = template.Library()
            
            @register.filter(name='has_group')
            def has_group(user, group_name):
                try:
                    group =  Group.objects.get(name=group_name)
                except Group.DoesNotExist:
                    return False
            
                return group in user.groups.all()
            

            您的模板:

            {% if request.user|has_group:"mygroup" %} 
                <p>User belongs to my group 
            {% else %}
                <p>User doesn't belong to mygroup</p>
            {% endif %}
            

            【讨论】:

            • 这是一个更好的答案,因为它使用 try/catch 块,如果用户不属于该组,则不会在您的模板中出错。
            【解决方案11】:

            在您的模板中

            {% ifequal user.groups.all.0.name "user" %}
              This is User
            {% endifequal %}
              

            【讨论】:

            • 如果用户属于单个组,这将非常有效。如果一个用户属于多个组,是否有一种简单的方法可以修改它以便我们不只检查 all.0.name?
            • @LNI 我正在寻找相同的答案。我不想硬编码任何组名。如果有人决定更改组、名称,请考虑返工。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-06-15
            • 1970-01-01
            • 2012-08-15
            • 2011-06-14
            • 1970-01-01
            • 2016-07-18
            • 2020-08-22
            相关资源
            最近更新 更多