python 覆盖现有的Django模板标签

0ve6wy6x  于 2023-05-16  发布在  Python
关注(0)|答案(7)|浏览(117)

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

myzjeezk

myzjeezk1#

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

rnmwe5a2

rnmwe5a22#

我假设你说的“一个现有的Django模板标签”是指另一个应用程序中的标签。
创建一个templatetags/tagfile.py,用相同的名称注册一个标记。确保tagfile与模板为获取原始标记而加载的{% load tagfile %}的名称相同。
此外,请确保您的应用程序在INSTALLED_APPS中的原始应用程序之后列出。

yiytaume

yiytaume3#

我很确定你是在要求完全覆盖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中包含要覆盖templatetag的应用程序:
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的admin admin_list.py的全部内容,而不仅仅是一段代码,否则它将无法工作!
它是如何工作的:Django正在应用程序中查找templatetags文件夹,并使用其中的模板标记。它将您的模板标记放置在admin's之后,简而言之-它覆盖它们,因为它们被放置在INSTALLED_APPS中的django.admin之后。
不要忘记:

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

在生产中。
我已经测试了它的result_list(cl)功能覆盖,它是工作。
此解决方案无需自定义html模板文件即可工作。
希望能帮上忙。

fcwjkofz

fcwjkofz4#

是的。
由于django基本上是一个python库(就像python中的所有东西一样),你可以覆盖任何你想要的东西。
目前还不清楚你到底想做什么,但它真的很容易滚动自己的templatetag,文档很清楚: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

kb5ga3dv

kb5ga3dv5#

如果你不想依赖于你的应用在settings.py INSTALLED_APPS中的顺序,那么你可以尝试以下操作:
像往常一样创建templatetag函数/类。假设您想要覆盖名为other_app的应用程序中名为otherapp_tags.current_time的templatetag。首先,创建您自己的函数/类版本:

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()方法中执行此操作。

mv1qrgav

mv1qrgav6#

实际上投票最多的解决方案对我来说有一个主要的缺点-你需要重新定义所有的标签。对于一些项目来说,这可能是一个很大的缺点。怎么解决呢?正如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模板标签。请注意,它适用于给定项目中的所有应用程序!

ioekq8ef

ioekq8ef7#

你可以覆盖和创建Django模板标签。
首先,在core文件夹中创建templatetags文件夹,其中包含__init__.py(空文件)和custom_tags.py,其中settings.py如下所示,然后不要忘记重新启动服务器以将custom_tags.py应用到Django项目。* 其他名称对于custom_tags.py也很好,你可以看到我解释templatetags文件夹和load标签的答案:

Django Project
 |-core
 |  |-settings.py
 |  └-templatetags # Here
 |     |-__init__.py
 |     └-custom_tags.py
 |-templates
 |  └-index.html
 |-app1
 └-app2

并且,不要忘记在settings.py中将core设置为INSTALLED_APPS,以将custom_tags.py应用于Django项目,如下所示。* 将core设置为INSTALLED_APPS也可以使用python manage.py collectstaticcore文件夹中的静态文件收集到Django Project根文件夹中。我建议在开始构建Django项目之前将core设置为INSTALLED_APPS

# "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.

接下来,在custom_tags.py中创建带有@register.simple_tag的uppercase标记,如下所示。* 这一次,你不需要重启服务器,因为你已经重启了服务器来将custom_tags.py应用到Django项目:

# "custom_tags.py"

from django.template import Library

register = Library()

@register.simple_tag
def uppercase(arg):
    return arg.upper()

然后,使用uppercase标记,如下所示:

# "templates/index.html"

{% load custom_tags %}

{% uppercase "Hello World" %}

然后,将显示以下内容:

HELLO WORLD

相关问题