在阅读了关于线程安全性的this document之后,我感到文档中缺少了一些东西,或者我对它的阅读,或者我的推理。在
举个简单的例子:
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()
我理解这段代码是为了在使用hello_world
标记时构造HelloWorldNode
类的新实例。其他示例包括向构造函数传递参数,如下所示:
因此,当执行hello_world
时,将创建HelloWorldNode的新实例,并且实例字典具有属性message
。当然,这个实例必须仅用于标记的给定实例的呈现,因为将其用于其他渲染将意味着绑定到它的数据将不正确。如果不是这样的话,参数会在标记的不同用法之间混淆。在
查看文档中的其他示例,下面是一个来自here的简化示例:
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()
doc说,如果两个页面使用同一个节点,那么使用同一个标记的两个页面可能会遇到竞争条件。我不明白如果两个模板都独立地实例化自己的实例,那么两个模板的呈现怎么会共享同一个实例。
解决这个问题的方法是这样的,文档是这样说的:
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()
这似乎是用self
索引context.render_context
。这意味着self
用于通过以下两种方式之一标识实例:
self
在整个系统中引用该类的一个特定实例self
只引用该类,为了引用实例,需要呈现上下文如果1为真,为什么不将数据与self
关联起来呢?在
如果2为真,并且呈现上下文是“与当前正在呈现的模板的上下文相关联”,那么如何区分同一页上模板标记的两个实例?在
每次调用标记时节点是否单独实例化?如果是,为什么会出现并发问题?如果没有,为什么不呢?在
仔细阅读this就知道了。在
模板在加载时被编译。传入tag函数的任何参数都是“static”。它们要么是文本字符串,要么是用作标识符在呈现上下文中查找绑定变量的字符串。在
因此,Node对象被实例化为每个标记,并在使用模板时挂起以备使用(当然,模板可以在任意数量的线程中使用)。在
因此,我的问题中的
self
是模板中特定节点的标识。结合呈现上下文,这将提供一个唯一的标识,用于挂起实例变量。在相关问题 更多 >
编程相关推荐