2010-09-15 17 views
7

Non so se è possibile, ma mi piacerebbe essere in grado di scrivere qualcosa di simile a quanto segue:Creazione di un elenco al volo in un modello di Django

{% with var1 var2 var3 as some_list %} 
    {{ some_list|maximum }} 
{% endwith %} 

Creazione di un elenco al volo da un numero arbitrario di variabili di template e/o letterali sembra utile, quindi sono fiducioso di aver trascurato qualcosa di semplice.

In caso contrario, mi piacerebbe sapere come creare un tag modello che accetta un numero arbitrario di argomenti. (Ho giocato in giro con simple_tag, che funziona bene per i tag che accettano un numero fisso di argomenti.)

Io non voglio andare alla difficoltà di creare un parser e sottoclasse django.template.Node fino a quando ho constatato che non c'è una soluzione più semplice.

risposta

13

Se si desidera aggiungere una nuova variabile (ad esempio some_list), è necessario accedere al contesto del modello, quindi simple_tag non sarà sufficiente.

Per me, il primo approccio è provare a fare questo tipo di lavoro nella vista, al fine di mantenere i modelli il più semplice possibile.

Se questo non è necessario, si dovrà scrivere il tag manualmente, in questo modo:

@register.tag 
def make_list(parser, token): 
    bits = list(token.split_contents()) 
    if len(bits) >= 4 and bits[-2] == "as": 
    varname = bits[-1] 
    items = bits[1:-2] 
    return MakeListNode(items, varname) 
    else: 
    raise template.TemplateSyntaxError("%r expected format is 'item [item ...] as varname'" % bits[0]) 

class MakeListNode(template.Node): 
    def __init__(self, items, varname): 
    self.items = map(template.Variable, items) 
    self.varname = varname 

    def render(self, context): 
    context[self.varname] = [ i.resolve(context) for i in self.items ] 
    return "" 

e utilizzarlo come questo per creare una nuova variabile some_list:

{% make_list var1 var2 var3 as some_list %} 

Sentitevi liberi per dargli un nome migliore!

+2

+1. Questa soluzione consente di salvare l'elenco risultante in un'altra variabile, consentendoti di operare in seguito. –

+0

Grazie, Will. Questo va bene per il conto. Il motivo per cui l'elaborazione nella vista non è un'opzione è che sto creando un modello per un'app Django riutilizzabile. La vista fornisce un elenco completo di elementi. All'interno del modello sto impostando il numero massimo di elementi da visualizzare usando '{% con 5 come% massimo}'. Oltre ad emettere il numero appropriato di elementi, includo un conteggio di visualizzazione nel formato "visualizzazione di X di articoli Y". X è o 'items | length' o' max', qualunque sia il più piccolo. Quindi ho bisogno di trovare il più piccolo dei due valori, uno dei quali è impostato all'interno del modello stesso. – davidchambers

+0

Dovrebbe essere 'len (bit)> 3' anziché' len (bit)> 4' per consentire una lista con un singolo oggetto da creare. – davidchambers

3

Ho giocato un po 'e ho trovato un tag che può accettare un numero variabile di argomenti e convertirli in un elenco.

@register.tag('to_list') 
def to_list(_parser, token): 
    try: 
     parts = token.split_contents() 
    except ValueError: 
     raise template.TemplateSyntaxError, \ 
      "%r tag requires at least one argument" % token.contents.split()[0] 

    return AsListNode(parts[1:]) 

class AsListNode(template.Node): 
    def __init__(self, parts): 
     self.parts = map(lambda p: template.Variable(p), parts) 

    def render(self, context): 
     resolved = [] 
     for each in self.parts: 
      resolved.append(each.resolve(context)) 
     return resolved 

Template:

<p>{% to_list var1 var2 var3 %}</p> 

Aggiornamento

@solution di Will è meglio. Ti permette di salvare la lista risultante usando un'altra variabile in modo che tu possa operare su di essa in seguito.

Problemi correlati