Defining “global variable” in Django templates

后端 未结 5 894
情书的邮戳
情书的邮戳 2020-12-16 04:52

I\'m doing something like:

{% extends \'base.html\' %}
{% url myapp.views.dashboard object as object_url %}
{% block sidebar %}
... {{ object_url }} ...
{% e         


        
5条回答
  •  温柔的废话
    2020-12-16 05:33

    Looks like this was answered before, but there is an alternative. It's one thing to use a context processor to keep track of something defined from outside the template, but sometimes you want to count the number of times two loops go through, or something like that. There is another way:

    class GlobalVariable(object):
        def __init__(self, varname, varval):
            self.varname = varname
            self.varval = varval
    
        def name(self):
            return self.varname
    
        def value(self):
            return self.varval
    
        def set(self, newval):
            self.varval = newval
    
    
    class GlobalVariableSetNode(template.Node):
        def __init__(self, varname, varval):
            self.varname = varname
            self.varval = varval
    
        def render(self, context):
            gv = context.get(self.varname, None)
            if gv:
                gv.set(self.varval)
            else:
                gv = context[self.varname] = GlobalVariable(
                    self.varname, self.varval)
            return ''
    
    
    def setglobal(parser, token):
        try:
            tag_name, varname, varval = token.contents.split(None, 2)
        except ValueError:
            raise template.TemplateSyntaxError(
                "%r tag requires 2 arguments" % token.contents.split()[0])
        return GlobalVariableSetNode(varname, varval)
    
    
    register.tag('setglobal', setglobal)
    
    
    class GlobalVariableGetNode(template.Node):
        def __init__(self, varname):
            self.varname = varname
    
        def render(self, context):
            try:
                return context[self.varname].value()
            except AttributeError:
                return ''
    
    
    def getglobal(parser, token):
        try:
            tag_name, varname = token.contents.split(None, 1)
        except ValueError:
            raise template.TemplateSyntaxError(
                "%r tag requires arguments" % token.contents.split()[0])
        return GlobalVariableGetNode(varname)
    
    
    register.tag('getglobal', getglobal)
    
    
    class GlobalVariableIncrementNode(template.Node):
        def __init__(self, varname):
            self.varname = varname
    
        def render(self, context):
            gv = context.get(self.varname, None)
            if gv is None:
                return ''
            gv.set(int(gv.value()) + 1)
            return ''
    
    
    def incrementglobal(parser, token):
        try:
            tag_name, varname = token.contents.split(None, 1)
        except ValueError:
            raise template.TemplateSyntaxError(
                "%r tag requires arguments" % token.contents.split()[0])
        return GlobalVariableIncrementNode(varname)
    
    
    register.tag('incrementglobal', incrementglobal)
    

    This allows you to use it in a template like this:

    {% setglobal ii 0 %}
    ...
    {% for ... %}
      {% incrementglobal ii %}
      current={% getglobal ii %}
    {% endfor %}
    ...
    {% for ... %}
      {% incrementglobal ii %}
      current={% getglobal ii %}
    {% endfor %}
    ...
    total of 2 loops={% getglobal ii %}
    ...
    {% setglobal ii 0 %}
    ...
    do something else now that {% getglobal ii %} is back to 0
    

提交回复
热议问题