Безопасность темы с тегами шаблона - PullRequest
8 голосов
/ 20 сентября 2011

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

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

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 Ответ

0 голосов
/ 20 сентября 2011

Получил при более близком прочтении this .

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...