После прочтения этого документа о безопасности потоков, у меня осталось ощущение, что в документации чего-то не хватает, или мое чтение, или мои рассуждения.
Давайте простопример:
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
используется для идентификации экземпляра одним из двух способов:
self
ссылается на один конкретный экземпляр класса во всей системе self
ссылается только на этот класс, и для ссылки на экземпляр необходим контекст визуализации
Если 1 истинно, почему бы просто не связать данные с self
?
Если 2 имеет значение true, а контекст рендеринга «связан с контекстом шаблона, который отображается в данный момент», как можно отличить два экземпляра тега шаблона на одной странице?
Создается ли узел индивидуально каждый раз, когда вызывается тег?Если да, то почему проблемы с параллелизмом?Если нет, то почему?