根据用户是否为员工在模板中定义变量

0 投票
1 回答
1955 浏览
提问于 2025-04-16 06:48

我想展示一个包含大约20列的HTML表格,其中员工用户可以看到一部分列,而非员工用户则看到另一部分列。以后我可能还想定义更多类型的用户。目前,我有三行固定的表头,所以模板看起来是这样的:

<table>
<tr>
  <th>Col A</th>
  {% if user.is_staff %}<th>Col B</th>{% endif %}
  ...
  {% if not user.is_staff %}<th>Col K</th>{% endif %}
</tr>
<tr>
  <td>Col A second header</td>
  {% if user.is_staff %}<td>Col B second header</td>{% endif %}
  ...
  {% if not user.is_staff %}<td>Col K second header</td>{% endif %}</tr>
<tr><td>Col A third header</td>  ...  </tr>

{% for obj in object_list %}
<tr>
  <td>{{ obj.col_a }}</td>
  {% if user.is_staff %}<td>{{ obj.col_b }}</td>{% endif %}
  ...
  {% if not user.is_staff %}<td>{{ obj.col_k }}</td>{% endif %}
</tr>
{% endfor %}</table>

不过,我发现这样不太方便,因为每次如果我想改变某个用户类型能否看到某一列,我就得在四个地方都改一次。如果我想定义多种不同的用户类别,就得写复杂的条件语句。我更希望能有这样的方式:

 {% if show_col_a %}<td>{{obj.col_a }}</td>{{% endif %}

在模板的顶部(或者可能在视图中)定义用户.is_staff可以看到show_col_a。这样做可以吗?我正在使用一个通用视图(object_list)。也许可以让所有用户都有属性user.show_col_a,然后用{% if user.show_col_a %}来判断?我不太确定怎么给用户添加布尔属性。

补充:我可能想要多个用户有自定义视图(比如,staff_view;admin_view,普通用户等),这样条件语句会变得很复杂。一个单元格的内容通常比{{ obj.col_b }}复杂;我试着简化问题以便更清楚。例如:

<td>{% if obj.custom_address %}
  {{ obj.custom_address.webprint|safe }}
{% else %}
  {{ obj.business.address.webprint|safe }}
{% endif %}</td>

另外,虽然多个模板可以通过简单的切换来实现:

{% if user.is_staff %}
   {% include "template_staff.html" %}
{% else %}{% if user.is_admin %}
   {% include "template_admin.html" %}
{% else %}
   {% include "template_other.html" %}
{% endif %}
{% endif %}

但我发现这样一点也不方便;例如,每次编辑模板都得在三个模板中重复一遍。我想我可以写一个脚本,从某个超模板生成这三个模板,但这样做就显得很不优雅了。

1 个回答

2

这主要取决于你使用的视图和模板。

可以尝试的方法有:

  • 创建一个公共模板和一个员工模板,并添加一个简单的方法,可以在视图中动态切换这两个模板。
  • 制作一个模板标签:

    {% is_staff myvar %}

标签代码:

class IsStaffNode(Node):
    def __init__(self, var):
        self.var = var

    def render(self, context):
        if context['user'].is_staff():
            return var.resolve(context)
        return ""


@register.tag
def is_staff(parser, token):
    var = parser.compile_filter(token.split_contents()[1])
    return IsStaffNode(var)

作业:把它做成一个块标签,以便可以显示所有的单元格,或者一个都不显示。

{% isstaff myvar %}<td>{{ myvar }}</td>{% endisstaff %}

这种方法比使用两个不同的模板要复杂一些,但如果你想尝试,可以操作上下文(或者为这个块创建一个单独的上下文)可能会有帮助

  • 创建一个上下文处理器,如果用户是员工,就填充一些变量到上下文中,否则就不填充。
  • 制作一个标签,包含模板(继承自IncludeNode),并操作上下文。

撰写回答