是否可以覆盖现有的Django模板标签?还是必须自定义模板文件并创建新的模板标签?
是否可以覆盖现有的Django模板标签?还是必须自定义模板文件并创建新的模板标签?
我也在寻找同样的答案,所以想在这里分享我的解决方案。我希望覆盖Django中默认的URL模板标签,而不必使用自定义模板标签并在每个模板文件中加载它。
目标是将 %20(空格)替换为 + (加号)。这是我想出来的解决方法...
在 __init__.py
中:
from django.template.defaulttags import URLNode
old_render = URLNode.render
def new_render(cls, context):
""" Override existing url method to use pluses instead of spaces
"""
return old_render(cls, context).replace("%20", "+")
URLNode.render = new_render
这个页面很有用 https://github.com/django/django/blob/master/django/template/defaulttags.py
templatetags/tagfile.py
的文件,并注册相同名称的标签。 确保tagfile
是模板使用{% load tagfile %}
加载原始标签的相同名称。INSTALLED_APPS
中列在原始应用程序之后。register
对象(另一个库应该有类似于register = template.Library()
的东西,然后通过执行@register.tag
等来注册标签)。你可以导入register
而不是实例化自己,并执行@register.tag(tag_name='existing_tag')
。 - floer32(templates.E003) 'admin_list' 被多个模板标签模块使用:'myapp.templatetags.admin_list','someapp.templatetags.admin_list'
。 - mdr我非常确定您正在要求完全覆盖 Django 的 templatetag
。
简短的回答是——是的,您可以覆盖现有的 templatetag
。
以下是如何实现:
settings
中: TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'your_app/templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.static',
],
},
},
]
templatetag
的应用程序包含在INSTALLED_APPS
中:INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'your_app_name',
...
]
是的。
Django基本上是一个Python库(与Python中的所有内容一样),因此您可以覆盖任何想要的内容。
不清楚您想要做什么,但编写自定义模板标签真的非常容易,文档非常清晰:https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags
这很基础,但这是我用来开始构建自定义模板标签的模板:
myapp/templatetags/my_custom_tags.py
(此目录中必须有__init__.py
)
from django import template
register = template.Library()
class CustomTag(template.Node):
def render(self, context):
context['my_custom_tag_context'] = "this is my custom tag, yeah"
return ''
@register.tag(name='get_custom_tag')
def get_custom_tag(parser, token):
return CustomTag()
在模板中使用的方法如下:
{% load my_custom_tags %}
{% get_custom_tag %}
{{my_custom_tag_context}}
token
,并且您可能需要在类中添加某种形式的 __init__
,但这表明它有多基础。
您可以浏览现有的“默认”模板标签,复制并修改它们以符合您的需求。
那里确实有一些很棒的东西: https://github.com/django/django/blob/master/django/template/defaulttags.py
实际上得票最多的解决方案对我来说有一个主要的缺点-您需要重新定义所有标记。 对于某些项目,这可能是一个很大的缺点。 如何解决?正如m_floer所提到的那样,最好从外部模块导入注册实例。那么它应该是什么样子?代码来自Django Jazzmin:
我想做什么?覆盖唯一的模板标记:get_side_menu
标记。
该标记位于jazzmin.templatetags.jazzmin
中,因此在我们的应用程序中,我们将创建带有文件jazzmin.py
的模块templatetags
。内容如下:
...
from jazzmin.templatetags.jazzmin import register
@register.simple_tag(takes_context=True, name="get_side_menu")
def get_side_menu(context: Context, using: str = "available_apps") -> List[Dict]:
... # your template tag code
这将以最简单的方式覆盖仅选择的Django模板标签。请注意,这适用于给定项目中的所有应用程序!
INSTALLED_APPS
,那么可以尝试以下方法:otherapp_tags.current_time
的templatetag,该templatetag来自名为other_app
的app。首先,创建您自己的版本的函数/类:def my_current_time(format_string):
return datetime.datetime.now().strftime(format_string)
那么,不要在您的应用程序命名空间中注册此函数/类,而是修补来自其他应用程序的现有函数:
from other_app.templatetags import otherapp_tags
otherapp_tags.register.tags['current_time'] = my_current_time
通常应该在您的AppConfig
的ready()
方法中执行此操作。
settings.py
所在的core
文件夹中创建templatetags
文件夹,并在其中创建__init__.py
(空文件)和custom_tags.py
,如下所示。然后不要忘记重新启动服务器,以应用custom_tags.py
到Django项目。*对于custom_tags.py
,其他名称也可以,你可以看到我的回答,解释了templatetags文件夹和加载标签:django-project
|-core
| |-settings.py
| └-templatetags # Here
| |-__init__.py
| └-custom_tags.py
|-templates
| └-index.html
|-app1
└-app2
# "core/settings.py"
INSTALLED_APPS = [
# ...
'core', # Here
'app1',
'app2',
]
custom_tags.py
中覆盖comment
标签,如下所示。*您可以在/django/template/defaulttags.py
中查看原始的评论标签:# "custom_tags.py"
from django.template import Library, Node
register = Library()
@register.tag
def comment(parser, token):
parser.skip_past('endcomment')
return CommentNode()
class CommentNode(Node):
def render(self, context):
return 'This is not a comment.' # This part is changed.
然后,如下所示使用重写的注释标签:
# "templates/index.html"
{% load custom_tags %}
{% comment %}{% endcomment %}
This is not a comment.