覆盖现有的 Django 模板标签

Posted

技术标签:

【中文标题】覆盖现有的 Django 模板标签【英文标题】:Override existing Django Template Tags 【发布时间】:2012-10-24 18:55:36 【问题描述】:

是否可以,或者是否需要自定义模板文件并创建新的模板标签?

【问题讨论】:

是的,有可能。例如***.com/a/13106661/165603 【参考方案1】:

是的。

由于 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

【讨论】:

好吧,这个例子展示了如何创建一个新的标签,但是如何在一个单独的 py 文件中覆盖这个现有的标签呢?我不想在不需要的时候触摸模板文件。【参考方案2】:

我假设“现有的 Django 模板标签”是指不同应用程序中的标签。

创建一个templatetags/tagfile.py,注册一个同名的标签。确保 tagfile 与模板加载的名称相同,% load tagfile % 用于获取原始标签。

另外,请确保您的应用列在 INSTALLED_APPS 中的原始应用之后。

【讨论】:

一个类似的想法:你可以从另一个库加载register对象(另一个库应该有类似register = template.Library()的东西,然后它通过@register.tag等注册标签。你可以导入register 而不是实例化你自己的,然后做@register.tag(tag_name='existing_tag') 这可能是最好的解决方案!【参考方案3】:

我一直在寻找相同的答案,所以想在这里分享我的解决方案。我想覆盖 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

【讨论】:

为了教化,这非常类似于 rails alias_method_chain 功能减去“无”语义。 @ncavig 你好,你是在哪个“init.py”中做的?【参考方案4】:

如果您不想在 settings.py INSTALLED_APPS 中依赖应用程序的顺序,那么您可以尝试以下操作:

像往常一样创建模板标签函数/类。假设您想从名为 other_app 的应用程序中覆盖名为 otherapp_tags.current_time 的模板标签。首先,创建您自己的该函数/类的版本:

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

通常您应该在 AppConfigready() 方法中执行此操作。

【讨论】:

【参考方案5】:

我很确定您要求完全覆盖 django templatetag

简短的回答是 - Yes,您可以覆盖现有的 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',
                ],
            ,
        ,
    ]
您必须在 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 的应用之后!

这是由于 django 的工作方式。我们将获得使用权。

现在,在您的应用程序中创建一个文件夹,命名为 templatetags。在templatetags 中包含__init__.py 文件很重要,因此django 可以理解它是一个python 包!:

your_app_name/templatetags/__init__.py.

创建要覆盖的templatetag。在该示例中,我将使用 admin_list.py 标签。

在这种情况下,应该这样放置:

your_app_name/templatetags/admin_list.py

现在复制admin_list.py 的全部内容(非常重要!) 来自django.contrib.admin.templatetags.admin_list.py 并修改任何你想要的。

重要的是要拥有django的adminadmin_list.py的全部内容,而不仅仅是一段代码,否则它将无法工作!


它是如何工作的: Django 正在您的应用程序中查找templatetags 文件夹并使用其中的模板标签。它将您的模板标签放在 admin's 之后,简而言之 - 它会覆盖它们,因为它们被放置在 INSTALLED_APPS 中的 django.admin 之后。

别忘了:

./manage.py collectstatic 设置DEBUG = False

正在生产中。

我已经为result_list(cl) 函数覆盖测试了它,它正在工作。


此解决方案在没有自定义 html 模板文件的情况下有效。

希望对您有所帮助。

【讨论】:

没有办法“扩展”现有的模板标签文件,类似于我们使用 Django 模板的方式?

以上是关于覆盖现有的 Django 模板标签的主要内容,如果未能解决你的问题,请参考以下文章

Django 覆盖表单 HTML 标签模板?

覆盖管理模板时出现 TemplateSyntaxError

覆盖现有的jQuery窗口刷新

覆盖 Django 小部件默认模板

覆盖 Django 渲染方法

javascript模板继承