覆盖现有的Django模板标签

时间:2012-11-04 22:33:28

标签: django django-templates

是否可以覆盖现有的Django模板标签,还是需要自定义模板文件并创建新的模板标签?

5 个答案:

答案 0 :(得分:18)

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

答案 1 :(得分:8)

我认为“现有的Django模板标签”是指不同应用中的标签。

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

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

答案 2 :(得分:2)

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

答案 3 :(得分:0)

如果您不希望依赖settings.py INSTALLED_APPS中应用程序的顺序,则可以尝试以下操作:

照常创建templatetag函数/类。假设您要从名为otherapp_tags.current_time的应用中覆盖名为other_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的{​​{1}}方法中执行此操作。

答案 4 :(得分:0)

我很确定您要完全重写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',
                ],
            },
        },
    ]
  • 您必须在其中包含要覆盖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的应用!

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

  • 现在,在您的应用程序中创建一个名为templatetags的文件夹。在__init__.py中放入templatetags文件很重要,因此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管理员admin_list.py的全部内容,不仅是一段代码,否则将是行不通的!


工作原理: Django在您的应用程序中寻找templatetags文件夹,并在其中使用模板标记。它将模板标记放置在admin's之后,并且简而言之-由于它们被放置在django.adminINSTALLED_APPS之后,因此它们会覆盖它们。

别忘了:

  • ./manage.py collectstatic
  • 设置DEBUG = False

生产中。

我已经对它进行了result_list(cl)功能覆盖测试,并且可以正常工作。


此解决方案适用于没有自定义html模板文件的事件。

希望有帮助。