模板中的自定义方法
- filter
- simple_tag
- inclusion_tag
filter
filter 默认只能接收两个参数:第一个参数是传递给 filter 的变量(即管道符 | 前面的内容)。第二个参数是 filter 调用时传入的唯一显式参数。
如果需要更复杂的逻辑或多个参数,通常有两种做法:
- 将多个值合并为一个字符串传入(如下面的例子所示),然后在函数内部解析这个字符串。
- 使用 simple_tag 替代 filter,它支持任意数量的参数。
项目示例(编辑/删除所在表格列的权限)
需求:当用户没有编辑删除权限时,表格的操作列需要隐藏
web/templatetags/permission.py
from django.template import Library
from django.conf import settings
from django.urls import reverse
from django.utils.safestring import mark_safe
register = Library() # 创建一个模板标签库实例
def check_permission(request, name):
# 1.获取当前用户角色
role = request.nb_user.role
# 2.根据角色获取其权限字典
permission_dict = settings.NB_PERMISSION[role]
# 3.判断是否具有权限 name->"customer_add"
if name in permission_dict:
return True
if name in settings.NB_PERMISSION_PUBLIC:
return True
@register.filter
def has_permission(request, others):
name_list = others.split(',')
for name in name_list:
status = check_permission(request, name)
if status:
return True
return False
HTML模板
request是传递给 has_permission 函数的主要输入值,"level_edit,level_delete"是传递给 has_permission 函数的额外参数
{% if request|has_permission:"level_edit,level_delete" %}
<th>操作</th>
{% endif %}
simple_tag
simple_tag可以接收任意数量的参数,可以在模板中像函数一样调用,支持位置参数和关键字参数。常用于生成HTML片段或复杂内容。
项目示例(编辑/删除按钮权限)
需求:当用户没有编辑、删除权限时,button需要隐藏
@register.simple_tag
def edit_permission(request, name, *args, **kwargs):
# 4.无权限,返回空字符串
if not check_permission(request, name):
return ""
# 5.有权限,通过"customer_add"反向生成URL
url = reverse(name, args=args, kwargs=kwargs)
tpl = """
<a href="{}" class="btn btn-primary btn-xs">编辑</a>
""".format(url)
return mark_safe(tpl)
@register.simple_tag
def delete_permission(request, name, *args, **kwargs):
# 4.无权限,返回空字符串
if not check_permission(request, name):
return ""
# 5.有权限,生成HTML片段
pk = kwargs.get('pk')
tpl = """
<a cid={} class="btn btn-danger btn-xs btn-delete">删除</a>
""".format(pk)
return mark_safe(tpl)
@register.simple_tag
def delete_url_permission(request, name, *args, **kwargs):
# 4.无权限,返回空字符串
if not check_permission(request, name):
return ""
# 5.有权限,生成HTML片段
url = reverse(name, args=args, kwargs=kwargs)
tpl = """
<a href={} class="btn btn-danger btn-xs">删除</a>
""".format(url)
return mark_safe(tpl)
HTML模板 policy_list.html
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>数量</th>
<th>价格</th>
{% if request|has_permission:"policy_edit,policy_delete" %}
<th>操作</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for row in page.queryset %}
<tr row-id="{{ row.id }}">
<td class="td_class">{{ row.id }}</td>
<td class="td_class">{{ row.count }}</td>
<td class="td_class">{{ row.price }}</td>
<td class="td_class">
{% edit_permission request 'policy_edit' pk=row.id %}
{% delete_permission request 'policy_delete' pk=row.id %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
inclusion_tag
inclusion_tag专门用于渲染可重用的模板片段。专门用于渲染预定义的模板片段,可以处理复杂的数据逻辑并传递给模板,适合创建复杂的可重用UI组件。
项目示例(左侧菜单栏)
需求:左侧菜单栏层级显示并将菜单中当前所在功能页选中
layout.html
<div class="left-menu">
<div class="menu-body">
{% nb_menu request %} {# 加载menu.py中的nb_menu 将request参数传入nb_menu方法 #}
</div>
</div>
web/templatetags/menu.py
from django.template import Library
from django.conf import settings
import copy
register = Library() # 创建一个模板标签库实例
@register.inclusion_tag("tag/nb_menu.html") # 装饰器表明这个标签会渲染指定的模板
def nb_menu(request):
# 1.读取当前用户的角色信息
# 2.菜单信息
user_menu_list = copy.deepcopy(settings.NB_MENU[request.nb_user.role])
for item in user_menu_list:
for child in item['children']:
if child['name'] == request.nb_user.menu_name:
child['class'] = 'active'
return {'menu_list': user_menu_list} # 将menu_list传递给nb_menu.html
web/template/tag/nb_menu.html
<div class="multi-menu">
{% for item in menu_list %}
<div class="item">
<div class="title">
<span class="icon-wrap"><i class="fa {{ item.icon }}"></i></span> {{ item.text }}
</div>
<div class="body">
{% for child in item.children %}
<a class="{{ child.class }}" href="{{ child.url }}">{{ child.text }}</a>
{% endfor %}
</div>
</div>
{% endfor %}
</div>

被折叠的 条评论
为什么被折叠?



