【Django】模板中的自定义方法(filter、simple_tag、inclusion_tag)

模板中的自定义方法

  1. filter
  2. simple_tag
  3. inclusion_tag

filter

filter 默认只能接收两个参数:第一个参数是传递给 filter 的变量(即管道符 | 前面的内容)。第二个参数是 filter 调用时传入的唯一显式参数。

如果需要更复杂的逻辑或多个参数,通常有两种做法:

  1. 将多个值合并为一个字符串传入(如下面的例子所示),然后在函数内部解析这个字符串。
  2. 使用 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>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故林丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值