定义;全局变量";在Django模板中

定义;全局变量";在Django模板中,django,django-templates,Django,Django Templates,我在做一些事情,比如: {% extends 'base.html' %} {% url myapp.views.dashboard object as object_url %} {% block sidebar %} ... {{ object_url }} ... {% endblock %} {% block content %} ... {{ object_url }} ... {% endblock %} Django文档说url templatetag可以在上下文中定义一个变量,

我在做一些事情,比如:

{% extends 'base.html' %}
{% url myapp.views.dashboard object as object_url %}
{% block sidebar %}
... {{ object_url }} ...
{% endblock %}
{% block content %}
... {{ object_url }} ...
{% endblock %}
Django文档说url templatetag可以在上下文中定义一个变量,但是在下面的代码块中,我没有得到
object\u url
的任何值

如果我把url templatetag放在每个块的开头,它会工作,但我不想“重复我自己”


有人知道更好的解决方案吗?

如果URL是特定于视图的,您可以从视图中传递URL。如果URL在模板中需要真正的全局性,可以将其放入


这是一种滥用模板继承的行为,但您可以使用它将object_url放入块中

换句话说,在中级模板中,请执行以下操作:

{% block sidebar %}{{ object_url }}{% endblock %}
{% block content %}{{ object_url }}{% endblock %}
然后在块模板中使用:

{% block sidebar %}
... {{ block.super }}...
{% endblock %}

这不是一个好主意,因为它阻止您将
{{{object\u url}}}
之外的任何内容放入块中。。。但它是有效的。别告诉任何人你是从我这里得到的

在每个继承的模板中,不会执行块重新定义之外的任何代码。因此,在您的示例中,您必须在每个块内调用
{%url%}
标记,或者使用上下文处理器设置“全局”变量。

看起来这是以前回答过的,但还有一种选择。使用上下文处理器跟踪从模板外部定义的内容是一回事,但有时您需要计算两个循环经过的次数,或者类似的次数。还有另一种方法:

类全局变量(对象):
定义初始化(self,varname,varval):
self.varname=varname
self.varval=varval
def名称(自我):
返回self.varname
def值(自身):
返回self.varval
def设置(自身、新值):
self.varval=newval
类GlobalVariableSetNode(template.Node):
定义初始化(self,varname,varval):
self.varname=varname
self.varval=varval
def呈现(自身、上下文):
gv=context.get(self.varname,无)
如果gv:
gv.set(自变量)
其他:
gv=context[self.varname]=GlobalVariable(
self.varname,self.varval)
返回“”
def setglobal(解析器、令牌):
尝试:
tag_name,varname,varval=token.contents.split(无,2)
除值错误外:
raise template.TEMPLATESYNTASERROR(
%r标记需要2个参数“%token.contents.split()[0])
返回GlobalVariableSetNode(varname,varval)
register.tag('setglobal',setglobal)
类GlobalVariableGetNode(template.Node):
定义初始化(self,varname):
self.varname=varname
def呈现(自身、上下文):
尝试:
返回上下文[self.varname].value()
除属性错误外:
返回“”
def getglobal(解析器、令牌):
尝试:
tag_name,varname=token.contents.split(无,1)
除值错误外:
raise template.TEMPLATESYNTASERROR(
%r标记需要参数“%token.contents.split()[0])
返回GlobalVariableGetNode(varname)
register.tag('getglobal',getglobal)
类GlobalVariableIncrementNode(template.Node):
定义初始化(self,varname):
self.varname=varname
def呈现(自身、上下文):
gv=context.get(self.varname,无)
如果gv为无:
返回“”
gv.set(int(gv.value())+1)
返回“”
def incrementglobal(解析器、令牌):
尝试:
tag_name,varname=token.contents.split(无,1)
除值错误外:
raise template.TEMPLATESYNTASERROR(
%r标记需要参数“%token.contents.split()[0])
返回GlobalVariableIncrementNode(varname)
register.tag('incrementglobal',incrementglobal)
这允许您在如下模板中使用它:

{%setglobal ii 0%}
...
{对于…%}
{%incrementglobal ii%}
当前={%getglobal ii%}
{%endfor%}
...
{对于…%}
{%incrementglobal ii%}
当前={%getglobal ii%}
{%endfor%}
...
2个循环的总数={%getglobal ii%}
...
{%setglobal ii 0%}
...
现在{%getglobal ii%}已返回到0,请执行其他操作

您可以编写自定义模板标记:

@register.simple_tag(takes_context=True)
def set_global_context(context, key, value):
    """
    Sets a value to the global template context, so it can
    be accessible across blocks.

    Note that the block where the global context variable is set must appear
    before the other blocks using the variable IN THE BASE TEMPLATE.  The order
    of the blocks in the extending template is not important. 

    Usage::
        {% extends 'base.html' %}

        {% block first %}
            {% set_global_context 'foo' 'bar' %}
        {% endblock %}

        {% block second %}
            {{ foo }}
        {% endblock %}
    """
    context.dicts[0][key] = value
    return ''

嗯,很多视图使用这个变量,但不是全部。另外,我对自定义templatetags定义的另一种变量使用相同的模式。上面的例子只是简化了,所以我认为现在采用你的解决方案是不合适的。即使没有在每个模板中使用它,把它放到上下文处理器中也不会有什么坏处。。。当然,除非它在做数据库查找,否则它会影响站点性能。我个人应该补充一点,我更喜欢显式地在每个模板中加载。使我更容易准确地看到数据的来源。我自己也使用过这种方法,它对代码和可读性非常有效。在整个模板中随机编辑的全局变量可能很难调试。使用模板创建状态机可以将逻辑保持在一个位置,这有很多好处。很好的解决方案。我发现将其与“getattr(settings,name,”)结合使用非常有用,可以像“from django.conf import settings”中那样检索和存储设置。
@register.simple_tag(takes_context=True)
def set_global_context(context, key, value):
    """
    Sets a value to the global template context, so it can
    be accessible across blocks.

    Note that the block where the global context variable is set must appear
    before the other blocks using the variable IN THE BASE TEMPLATE.  The order
    of the blocks in the extending template is not important. 

    Usage::
        {% extends 'base.html' %}

        {% block first %}
            {% set_global_context 'foo' 'bar' %}
        {% endblock %}

        {% block second %}
            {{ foo }}
        {% endblock %}
    """
    context.dicts[0][key] = value
    return ''