Django Do Once Пользовательский тег шаблона - PullRequest
1 голос
/ 14 июля 2011

Я пытаюсь создать пользовательский тег шаблона, который отображает блок кода только один раз, независимо от того, сколько раз тег / фрагмент, содержащий его, выполняется.

Вот как я реализовалэто, но, как вы можете видеть, это немного хакерски:

my_partial.html:

{% once mycontent %}
    this will only show once
{% endonce%}

my_template.html:

{% load my_tags %}
{% for i in list %}
    {% my_partial %}
{% endfor %}

my_tags.py:

@register.inclusion_tag('my_partial.html',takes_context=True)
def my_partial(context):
    return dict(arbitrary extra data)

@register.tag(name="once")
def do_once(parser, token):
    try:
        # Splitting by None == splitting by spaces.
        tag_name, var_name = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0])
    nodelist = parser.parse(('endonce',))
    parser.delete_first_token()
    return DoOnceNode(nodelist, var_name)

class DoOnceNode(template.Node):
    def __init__(self, nodelist, var_name):
        self.nodelist = nodelist
        self.var_name = '_do_once_'+var_name
    def render(self, context):
        request = context['request']

        # Make request.GET mutable.
        request.GET = dict(request.GET)

        if self.var_name in request.GET:
            return ''
        else:
            request.GET[self.var_name] = 1
            return self.nodelist.render(context)

В частности, я использую словарь request.GET в качестве изменяемой глобальной области видимости.Это хакерское и, очевидно, не то, для чего предназначен объект запроса, но он работает.

В идеале я хотел бы использовать что-то вроде контекста, но я обнаружил, что он не разделяется между вызовами этоготег.то есть self.var_name in context всегда ложно, что делает его бесполезным в качестве глобальной области.

Почему контекст не передается так же, как и запрос?Есть ли какой-то способ сделать его действительно общим или есть какой-то другой объект, который я могу использовать для хранения глобально доступных переменных внутри запроса?

Ответы [ 2 ]

1 голос
/ 10 августа 2017

В результате я сохранил переменную в контексте и проверил ее в методе рендеринга узла:

class CustomNode(template.Node):
    def render(self, context: dict) -> str:
        context['already_rendered'] = context.get('already_rendered', set())

        if self.__class__ in context['already_rendered']:
            return ''

        context['already_rendered'].add(self.__class__)

        ...
1 голос
/ 14 июля 2011

Я не совсем уверен, что вам нужно сделать, или если ваш подход действительно лучший, но я бы посоветовал вам взглянуть на переменную forloop.first, прежде чем идти слишком далеко по этому пути. Ваш подход кажется в лучшем случае неловким с первого взгляда, но я могу ошибаться, поскольку не знаю специфики ситуации

django для тега шаблона

Скорее всего, вы сможете выполнить эту работу в соответствии с вашими потребностями, однако, если она не дотягивает, я бы предположил, что источник тега шаблона for (и его переменная forloop), вероятно, будет очень показательным как вы можете реализовать то, что вы хотите сделать.

...