Pergunta

Estou fazendo algo como:

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

A documentação do Django diz object_url nos blocos a seguir.

Se eu colocar o URL TemplateTag no início de cada bloco, ele funciona, mas não quero "me repetir".

Alguém conhece uma solução melhor?

Foi útil?

Solução

Se o URL for específico, você poderá passar o URL da sua opinião. Se o URL precisar ser verdadeiramente global em seus modelos, você pode colocá -lo em Um processador de contexto:

def object_url(request):
    return {'object_url': reverse('myapp.views.dashboard')}

Outras dicas

Parece que isso foi respondido antes, mas há uma alternativa. Uma coisa é usar um processador de contexto para acompanhar algo definido de fora do modelo, mas às vezes você deseja contar o número de vezes que dois loops passam ou algo assim. Há outra maneira:

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)

Isso permite que você o use em um modelo como este:

{% 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

Você pode escrever uma tag de modelo personalizada:

@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 ''

Bem, isso é meio abusivo de herança de modelo, mas você pode usar {{block.super}} Para colocar object_url em seus blocos.

Em outras palavras, em seu modelo de nível médio:

{% block sidebar %}{{ object_url }}{% endblock %}
{% block content %}{{ object_url }}{% endblock %}

E então, em seus modelos de bloco, use:

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

Não é uma ótima ideia, porque impede que você coloque qualquer coisa além {{ object_url }} em seu quarteirão ... mas funciona. Só não diga a ninguém que você conseguiu de mim!

Em todos os modelos herdados, qualquer código fora dos blocos de redefinições não é executado. Então, no seu exemplo, você tem que ligar {% url %} Marque dentro de cada bloco ou use o processador de contexto para definir a variável "global".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top