带有可配置模板的Django包含标签

7y4bm7vi  于 2023-03-20  发布在  Go
关注(0)|答案(6)|浏览(100)

我已经创建了一个包含标签,但是我希望能够使模板可选地配置。似乎没有现成的支持,所以我想看看人们是如何做到这一点的-也许一个方法搜索模板目录中的一个特定的模板名称,然后回落到默认模板。

@register.inclusion_tag('foo.html', takes_context=True)
6l7fqoea

6l7fqoea1#

当我需要这样做时,我使用simple_tag:

from django.template import Library, loader, Context

@register.simple_tag(takes_context=True)
def my_tag(context, template_name):

    var1 = ...

    t = loader.get_template(template_name)
    return t.render(Context({
        'var1': var1,
        ...
    }))
p3rjfoxz

p3rjfoxz2#

这个帖子救了我的命:http://djangosnippets.org/snippets/1329/
关键是要添加一个“虚拟模板”:

{% extends template %}
qf9go6mv

qf9go6mv3#

inclusion_tag装饰器只是一个快捷方式--它是一种用特定的上下文呈现特定模板的简单方法。一旦你想离开它,它就不再能帮你了。但这只意味着你必须像文档中解释的那样写一个很长的标记,并将你想要的模板作为参数传递。

iyfjxgzm

iyfjxgzm4#

我曾经在一个项目中做过类似的事情,因为我们需要不止一个这样的inclusion标签,所以我基于django inclusion_tag decorator做了一个decorator。

# -*- coding: utf-8 -*-
from django import template
from inspect import getargspec
from django.template.context import Context
from django.template import Node, generic_tag_compiler, Variable
from django.utils.functional import curry

def inclusion_tag(register, context_class=Context, takes_context=False):
    def dec(func):
        params, xx, xxx, defaults = getargspec(func)
        if takes_context:
            if params[0] == 'context':
                params = params[1:]
            else:
                raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'")

        class InclusionNode(Node):
            def __init__(self, vars_to_resolve):
                self.vars_to_resolve = map(Variable, vars_to_resolve)

            def render(self, context):
                resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
                if takes_context:
                    args = [context] + resolved_vars
                else:
                    args = resolved_vars

                file_name, extra_context = func(*args)

                from django.template.loader import get_template, select_template
                if not isinstance(file_name, basestring) and is_iterable(file_name):
                    t = select_template(file_name)
                else:
                    t = get_template(file_name)
                self.nodelist = t.nodelist
                new_context = context_class(extra_context, autoescape=context.autoescape)
                # Copy across the CSRF token, if present, because inclusion
                # tags are often used for forms, and we need instructions
                # for using CSRF protection to be as simple as possible.
                csrf_token = context.get('csrf_token', None)
                if csrf_token is not None:
                    new_context['csrf_token'] = csrf_token
                return self.nodelist.render(new_context)

        compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode)
        compile_func.__doc__ = func.__doc__
        register.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
        return func
    return dec

你必须返回一个带有模板(或模板列表)和上下文指令的元组。注意你必须在装饰器调用中传递register(Library示例):

from somewhere import inclusion_tag
@inclusion_tag(register)
def display_formset(formset):
    template_name = FORMSET_TEMPLATES.get(formset.model,
        'includes/inline_formset.html')
    return (template_name, {'formset': formset})

希望这能帮上忙

4ioopgfo

4ioopgfo5#

一个解决方案可以是常规inclusion_tag,它将动态模板名称传递给context
就像这样:

# templatetags/tags.py

@register.inclusion_tag('include_tag.html', takes_context=True)
def tag_manager(context):
    context.update({
        'dynamic_template': resolve_template(context),
    })
    return context

和模板:

<!-- include_tag.html -->

{% include dynamic_template %}

这里的技巧是,当我调用{% tag_manager %}时,它包含include_tag.html,而include_tag.html又包含由resolve_template()返回的模板(为简洁起见,没有包含)。
希望这能帮上忙...

tjvv9vkg

tjvv9vkg6#

@cvng的answer的变体,不需要创建include_tag.html模板:

@register.inclusion_tag(template.Template('{% include dynamic_template %}'),
                        takes_context=True)
def dynamic_tag(context):
    context.update({
        'dynamic_template': 'path/to/your/template.html',
    })
    return context

相关问题