He encontrado una enlace tener un «switch» de la etiqueta de plantillas de Django, pero me pregunto si esto puede ser de alguna manera logra sin ella. Utilizando sólo las cosas que viene con Django? Básicamente hay otro camino, a continuación, el uso de múltiples ‘si’ o ‘ifequal declaraciones?

Gracias de antemano por los consejos/sugerencias.

  • +1 Gracias por el enlace, pero dicen que las plantillas no es para «programar» y la lógica de negocio

4 Comentarios

  1. 21

    Por desgracia, esto no es posible con el defecto motor de plantillas de Django. Vas a tener que escribir algo feo como este para emular un interruptor.

    {% if a %}
        {{ a }}
    {% else %}
        {% if b %}
            {{ b }}
        {% else %}
            {% if c %}
                {{ c }}
            {% else %}
                {{ default }}
            {% endif %}
        {% endif %}
    {% endif %}

    o si sólo uno si la condición puede ser cierto, y usted no necesita un defecto.

    {% if a %}
    {{ a }}
    {% endif %}
    {% if b %}
    {{ b }}
    {% endif %}
    {% if c %}
    {{ c }}
    {% endif %}

    Generalmente, cuando el motor de plantillas no es lo suficientemente potente como para lograr lo que desea que este es un signo de que el código debe ser trasladado a Django vista, en lugar de en la plantilla. Por ejemplo:

    # Django view
    if a:
      val = a
    elif b:
      val = b
    elif c:
      val = c
    else:
      val = default
    
    # Template
    {{ val }}
    • Como de Django 1.4, elif es compatible
    • Retirar el firstof filtro de plantilla, que se abrevia este. No estoy seguro de que, cuando se presentó.
  2. 49

    Como de Django 1.4, hay {% elif %}:

    {% if a %}
      thing
    {% elif b %}
      other thing
    {% elif c %}
      another thing
    {% endif %} 
    • Cuando se combina con el ‘con’ etiqueta que nos puede ser bastante dang cerca de un interruptor. {% with a=ya.expensive.bro %} {% if a=1 %} one {% elif a=2 %} two {% else %} uhh {% endif %} {% endwith %} … es solo un toque feo.
  3. 18

    A la anterior en responder: Sin la comprensión del caso de uso, han hecho suposiciones y criticó el interrogador. @Ber dice «all over the place», que no es, ciertamente, implícita en la pregunta. No es justo.

    Tengo un caso en el que me gustaría hacer un {% switch %} declaración en exactamente un lugar en mi Django plantilla. No sólo no es conveniente mover el equivalente de la instrucción switch en el código de Python, pero que en realidad iba a hacer tanto la vista y la plantilla es más difícil de leer y tomar condicional simple lógica que pertenece en un solo lugar y que se dividió en dos lugares.

    En muchos casos, donde me podía imaginar un {% switch %} (o un {% if %}) ser útil, no usando uno requiere poner HTML en una vista. Eso es mucho peor pecado y es por eso que {% if %} existe, en primer lugar. {% switch %} no es diferente.

    Afortunadamente, Django es extensible y varias personas han implementado interruptor. Salida:

    Interruptor de etiqueta de plantilla

    from django import template
    from django.template import Library, Node, VariableDoesNotExist
    register = Library()
    @register.tag(name="switch")
    def do_switch(parser, token):
    """
    The ``{% switch %}`` tag compares a variable against one or more values in
    ``{% case %}`` tags, and outputs the contents of the matching block.  An
    optional ``{% else %}`` tag sets off the default output if no matches
    could be found::
    {% switch result_count %}
    {% case 0 %}
    There are no search results.
    {% case 1 %}
    There is one search result.
    {% else %}
    Jackpot! Your search found {{ result_count }} results.
    {% endswitch %}
    Each ``{% case %}`` tag can take multiple values to compare the variable
    against::
    {% switch username %}
    {% case "Jim" "Bob" "Joe" %}
    Me old mate {{ username }}! How ya doin?
    {% else %}
    Hello {{ username }}
    {% endswitch %}
    """
    bits = token.contents.split()
    tag_name = bits[0]
    if len(bits) != 2:
    raise template.TemplateSyntaxError("'%s' tag requires one argument" % tag_name)
    variable = parser.compile_filter(bits[1])
    class BlockTagList(object):
    # This is a bit of a hack, as it embeds knowledge of the behaviour
    # of Parser.parse() relating to the "parse_until" argument.
    def __init__(self, *names):
    self.names = set(names)
    def __contains__(self, token_contents):
    name = token_contents.split()[0]
    return name in self.names
    # Skip over everything before the first {% case %} tag
    parser.parse(BlockTagList('case', 'endswitch'))
    cases = []
    token = parser.next_token()
    got_case = False
    got_else = False
    while token.contents != 'endswitch':
    nodelist = parser.parse(BlockTagList('case', 'else', 'endswitch'))
    if got_else:
    raise template.TemplateSyntaxError("'else' must be last tag in '%s'." % tag_name)
    contents = token.contents.split()
    token_name, token_args = contents[0], contents[1:]
    if token_name == 'case':
    tests = map(parser.compile_filter, token_args)
    case = (tests, nodelist)
    got_case = True
    else:
    # The {% else %} tag
    case = (None, nodelist)
    got_else = True
    cases.append(case)
    token = parser.next_token()
    if not got_case:
    raise template.TemplateSyntaxError("'%s' must have at least one 'case'." % tag_name)
    return SwitchNode(variable, cases)
    class SwitchNode(Node):
    def __init__(self, variable, cases):
    self.variable = variable
    self.cases = cases
    def __repr__(self):
    return "<Switch node>"
    def __iter__(self):
    for tests, nodelist in self.cases:
    for node in nodelist:
    yield node
    def get_nodes_by_type(self, nodetype):
    nodes = []
    if isinstance(self, nodetype):
    nodes.append(self)
    for tests, nodelist in self.cases:
    nodes.extend(nodelist.get_nodes_by_type(nodetype))
    return nodes
    def render(self, context):
    try:
    value_missing = False
    value = self.variable.resolve(context, True)
    except VariableDoesNotExist:
    no_value = True
    value_missing = None
    for tests, nodelist in self.cases:
    if tests is None:
    return nodelist.render(context)
    elif not value_missing:
    for test in tests:
    test_value = test.resolve(context, True)
    if value == test_value:
    return nodelist.render(context)
    else:
    return ""
    • Esto es genial! Creo que mi única novedad sería hacer es para que usted pueda especificar un with x as y y tienen que pasar y abajo a cada caso. Pero eso es un nicho requisito.
  4. 2

    En un muy vista general, la necesidad de una instrucción switch es un signo de que hay una necesidad de crear nuevas clases y los objetos que la captura de las diferentes «casos».

    Entonces, en lugar de «interruptor»ing por todo el lugar, sólo necesitas llamar a un método del objeto o referencia a un atributo de objeto y de su hacer.

    • Tiene sentido en un lenguaje de programación orientada a objetos, pero no en el lenguaje de plantillas de Django. Usted no puede / no debe «llamar a un método del objeto» para hacer la representación en el Django de la plantilla.

Dejar respuesta

Please enter your comment!
Please enter your name here