Безопасность темы с тегами шаблона

После прочтения этого документа о безопасности потоков у меня осталось ощущение, что в документации чего-то не хватает, или я это читаю, или мои рассуждения.

Давайте приведем простой пример:

class HelloWorldNode(template.Node):
    def render(self, context):
        return "O HAI LOL"

@register.tag(name="hello_world")
def hello_world(parser, tokens):
    """
    Greets the world with wide-eyed awe.
    """
    return HelloWorldNode()

Я понял этот код, чтобы построить новый экземпляр HelloWorldNode класс всякий раз, когда hello_world тег используется. Другие примеры включают передачу аргументов в конструктор, например:

class HelloWorldNode(template.Node):
    def __init__(self, message):
        self.message = message

    def render(self, context):
        return "O HAI LOL " + message

@register.tag(name="hello_world")
def hello_world(parser, tokens):
    """
    Greets the world with wide-eyed awe.
    """

    message = tokens.split_contents()[1]

    return HelloWorldNode(message)

Таким образом, когда hello_world выполняется, создается новый экземпляр HelloWorldNode, а словарь экземпляра имеет атрибут message, Этот экземпляр, безусловно, должен использоваться только для визуализации только данного экземпляра тега, поскольку использование его для других визуализаций будет означать, что привязанные к нему данные будут неверными. Если бы это было не так, аргументы были бы перепутаны между различными использованиями тега.

Глядя на другие примеры из документов, вот упрощенный пример здесь:

def do_current_time(parser, token):
    tag_name, format_string = token.split_contents()
    return CurrentTimeNode(format_string[1:-1])

Так как это берет данные из токенов, переданных в функцию, единственный способ, которым может работать CurrentTimeNode, - каждый раз создавать новый экземпляр. do_current_time вызывается.

Вернуться на страницу документации, где возникает диссонанс. Это "плохо".

class CycleNode(Node):
    def __init__(self, cyclevars):
        self.cycle_iter = itertools.cycle(cyclevars)
    def render(self, context):
        return self.cycle_iter.next()

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

Способ решить эту проблему, говорит документация, выглядит следующим образом:

class CycleNode(Node):
    def __init__(self, cyclevars):
        self.cyclevars = cyclevars
    def render(self, context):
        if self not in context.render_context:
            context.render_context[self] = itertools.cycle(self.cyclevars)
        cycle_iter = context.render_context[self]
        return cycle_iter.next()

Это похоже на индекс context.render_context с self, Смысл этого должен быть self используется для идентификации экземпляра одним из двух способов:

  1. self ссылается на один конкретный экземпляр класса во всей системе
  2. self ссылается только на этот класс, и для ссылки на экземпляр требуется контекст рендеринга

Если 1 верно, почему бы просто не связать данные с self?

Если 2 имеет значение true, а контекст рендеринга "связан с контекстом шаблона, который отображается в данный момент", как можно отличить два экземпляра тега шаблона на одной и той же странице?

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

1 ответ

Решение

Получил это при более внимательном прочтении этого.

Шаблон компилируется при загрузке. Все аргументы, передаваемые в функцию тега, являются "статическими". Это либо буквенные строки, либо строки, которые используются в качестве идентификаторов для поиска связанных переменных в контексте рендеринга.

Поэтому объект Node создается для каждого тега и остается готовым к использованию всякий раз, когда используется шаблон (и, естественно, шаблон может использоваться в любом количестве потоков).

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

Другие вопросы по тегам