如何为Django模板标签库按模板目录参数化以避免代码重复?
解决Django模板标签重复代码的方案
针对你需要同时支持Bootstrap和UIKit表单标签、避免代码重复的需求,以下两种方案均可行,且完全适配Django标签注册的生命周期:
方案一:工厂函数生成标签
将核心逻辑抽离为独立函数,再通过工厂函数批量生成绑定不同模板路径的标签:
from django import template register = template.Library() # 抽离核心逻辑,只写一次 def _form_row_core(fieldname, labelpos, labelsize, widgetsize): return { # 这里是你原来的返回内容,比如字段、布局参数等 'fieldname': fieldname, 'labelpos': labelpos, 'labelsize': labelsize, 'widgetsize': widgetsize } # 工厂函数:接收模板路径,返回绑定该模板的标签函数 def create_form_row_tag(template_path): @register.inclusion_tag(template_path) def form_row(fieldname, labelpos, labelsize, widgetsize): return _form_row_core(fieldname, labelpos, labelsize, widgetsize) return form_row # 注册两个不同版本的标签 bootstrap_form_row = create_form_row_tag('myforms/bootstrap/formrow.html') uikit_form_row = create_form_row_tag('myforms/uikit/formrow.html')
模板中使用时,分别调用对应的标签:
{# Bootstrap表单行 #} {% bootstrap_form_row "username" "left" "col-md-3" "col-md-9" %} {# UIKit表单行 #} {% uikit_form_row "username" "top" "uk-width-1-4" "uk-width-3-4" %}
方案二:基于类的标签实现
利用Django的InclusionTag基类,通过继承复用核心逻辑:
from django import template from django.template.base import InclusionTag register = template.Library() class BaseFormRowTag(InclusionTag): # 重写get_context方法,定义核心逻辑 def get_context(self, fieldname, labelpos, labelsize, widgetsize): return { 'fieldname': fieldname, 'labelpos': labelpos, 'labelsize': labelsize, 'widgetsize': widgetsize } # 实例化时传入不同模板路径,注册为不同标签 bootstrap_form_row = BaseFormRowTag('myforms/bootstrap/formrow.html') register.tag('bootstrap_form_row', bootstrap_form_row) uikit_form_row = BaseFormRowTag('myforms/uikit/formrow.html') register.tag('uikit_form_row', uikit_form_row)
使用方式和方案一完全一致。
这两种方案都是在模块加载阶段(Django标签注册的早期生命周期)执行,和直接用@register.inclusion_tag装饰器的时机完全一致,不会有任何执行顺序或生命周期的问题。
内容的提问来源于stack exchange,提问作者thebjorn
相关产品推荐
相关产品推荐

