是否可以预处理模板以删除其`% extends %` 标签?

Posted

技术标签:

【中文标题】是否可以预处理模板以删除其`% extends %` 标签?【英文标题】:Is it possible to preprocess a template to remove its `% extends %` tag?是否可以预处理模板以删除其`% extends %` 标签? 【发布时间】:2015-06-07 16:44:08 【问题描述】:

场景

我正在构建一个 SPA,并且需要能够将第 3 方应用模板呈现为部分页面中的部分。因此它们不能包含任何现有的 base.html 标记。

问题

我只需要对来自特定第 3 方应用程序的某些模板执行此操作,因为它的某些视图仍需要在 SPA 之外作为单独的页面呈现。所以我不能简单地创建自己的 base.html 文件,其中没有任何内容,以防止添加其他标记,因为这会影响每个模板。

目前,尽管我实际上并没有以任何方式更改模板,但我必须为这些特定模板的类似副本创建类似的内容,这只需从顶部删除 % extends "base.html" %

问题

有没有办法只预处理特定模板并删除其% extends % 标签?

【问题讨论】:

【参考方案1】:

这才是我真正需要的……

Any way to make % extends '...' % conditional? - Django

... 下面是我花了几个小时想出的解决方案,直到我终于意识到我真正想问的问题。无论如何我都会在这里发布它,以防其他人觉得它有用。

__init__.py

% extends % 在模板中始终必须位于首位,因此无法使用% load % 加载此标签。相反,它必须以与 django 标签相同的方式加载。

所以这需要去某个地方强制它立即运行。

# The `add_to_builtins` function changed module in 1.7
try:
    from django.template.loader import add_to_builtins
except ImportError:
    from django.template.base import add_to_builtins


add_to_builtins('my_app.templatetags.overriden_tags')

my_app/templatetags/overriden_tags.py

from django import template
from django.template.loader_tags import do_extends, ExtendsNode

register = template.Library()

@register.tag('extends')
def preventable_extends(parser, token):
    node = do_extends(parser, token)
    return PreventableExtendsNode(node.nodelist, node.parent_name)


class PreventableExtendsNode(ExtendsNode):

    def render(self, context):
        prevent = context.get('prevent_extends')
        if prevent == self.parent_name.var:
            return self.nodelist.render(context)
        return super(PreventableExtendsNode, self).render(context)

mixins.py

class PreventableExtendsMixin(object):

    def __init__(self, **kwargs):
        self.prevent_extends = kwargs.pop('prevent_extends')
        super(PreventableExtendsMixin, self).__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super(PreventableExtendsMixin, self).get_context_data(**kwargs)
        context['prevent_extends'] = self.prevent_extends
        return context

用法

from third_party_app import LoginView

class MyLoginView(PreventableExtendsMixin, LoginView):

    def __init__(self, **kwargs):
        kwargs['prevent_extends'] = 'base.html'
        super(MyLoginView, self).__init__(**kwargs)

【讨论】:

以上是关于是否可以预处理模板以删除其`% extends %` 标签?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Blade 模板 @extends

django 模板中的 % include % vs % extends %

Laravel Blade:@extend 一个(已经扩展的)子刀片?

PHP Smarty 模板 模板继承 {extends}

thinkphp 中区块block和模板继承extend用法举例

如何在 Django 模板上实现“返回”链接?