根据用户是否为员工在模板中定义变量
我想展示一个包含大约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),并操作上下文。