python - 线程安全与模板标签

标签 python django concurrency django-templates

看完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 类的新实例。其他示例涉及将参数传递给构造函数,如下所示:

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。这个实例肯定只能用于呈现标签的给定实例,因为将它用于其他呈现将意味着绑定(bind)到它的数据将是不正确的。如果不是这种情况,参数将在标签的不同用途之间混淆。

查看文档中的其他示例,这是来自 here 的简化示例:

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

由于它从传递给函数的 token 中获取数据,因此 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()

这似乎是用 self 索引 context.render_context。这意味着 self 用于以两种方式之一识别实例:

  1. self 在整个系统中引用该类的一个特定实例
  2. self 仅引用该类,为了引用实例,需要渲染上下文

如果 1 为真,为什么不直接将数据与 self 相关联?

如果 2 为真,并且渲染上下文“与当前正在渲染的模板的上下文相关联”,如何区分同一页面上模板标签的两个实例?

每次调用标签时是否单独实例化节点?如果是这样,为什么会出现并发问题?如果不是,为什么不呢?

最佳答案

通过仔细阅读 this 得到它.

模板在加载时编译。传递给标记函数的任何参数都是“静态”的。它们要么是文字字符串,要么是用作标识符以在呈现上下文中查找绑定(bind)变量的字符串。

因此为每个标签实例化 Node 对象,并在模板被使用时挂起以备使用(当然模板可以在任意数量的线程中使用)。

因此,我问题中的 self 是模板中特定节点的标识。与渲染上下文相结合,这为挂起实例变量提供了一个唯一标识。

关于python - 线程安全与模板标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7483490/

相关文章:

python - 使用 Pytest 在函数中模拟引发异常

django - 使所有内联表单集表单可选

c++ - 为什么 PyObject_Print 崩溃?

python - 我如何(或者应该)将 DataFrame 的 DataFrame 转换为多索引 DataFrame?

django - 通过 URL 参数进行数据库路由

c - C中的细粒度锁定

c++ - 互斥代码中发生死锁?

java - 编写并发代码、非阻塞代码

python - 如何在 pygame 中碰撞并降低玩家的生命值?

django - 多家公司使用django系统,同一个项目的小贴士