Come accedere a un elemento del dizionario in un modello Django?


181

Vorrei stampare il numero di voti ottenuti da ciascuna scelta. Ho questo codice in un modello:

{% for choice in choices %}
    {{choice.choice}} - {{votes[choice.id]}} <br />
{% endfor %}

votesè solo un dizionario mentre choicesè un oggetto modello.

Solleva un'eccezione con questo messaggio:

"Could not parse the remainder"

Risposte:


63

Per echeggiare / estendere il commento di Jeff, ciò che penso dovresti mirare è semplicemente una proprietà nella tua classe Choice che calcola il numero di voti associati a quell'oggetto:

class Choice(models.Model):
    text = models.CharField(max_length=200)

    def calculateVotes(self):
        return Vote.objects.filter(choice=self).count()

    votes = property(calculateVotes)

E poi nel tuo modello, puoi fare:

{% for choice in choices %}
    {{choice.choice}} - {{choice.votes}} <br />
{% endfor %}

Il tag modello è IMHO un po 'eccessivo per questa soluzione, ma non è nemmeno una soluzione terribile. L'obiettivo dei modelli in Django è di isolarti dal codice nei tuoi modelli e viceversa.

Proverei il metodo sopra e vedrei quale SQL genera l'ORM poiché non sono sicuro che mi farà precapitare le proprietà e creerò semplicemente una sottoselezione per la proprietà o se iterativamente / on- domanda eseguire la query per calcolare il conteggio dei voti. Ma se genera query atroci, puoi sempre popolare la proprietà nella tua vista con i dati che hai raccolto tu stesso.


grazie @john ewart, la tua soluzione ha funzionato per me. Sono un principiante di Django e Python e non riesco a capire come ottenere il sql generato da ORM.
Mohamed,

Puoi trovare la risposta a quel bit qui: docs.djangoproject.com/en/dev/faq/models/… È abbastanza semplice, in realtà e può essere visualizzato nel tuo modello o registrato con una funzione di registrazione, ma devi ricordati di attivare DEBUG affinché funzioni.
John Ewart,

questa soluzione è perfetta per un problema che ho riscontrato con i modelli di motore di app django templating + google. Vorrei poterti votare due volte.
Conrad.Dean,

5
Mentre funziona, non è molto efficiente. Sta eseguendo query sql in un ciclo (qualcosa che dovresti evitare). Creare il tuo tag per fare ricerche dict è facile: @ register.filter def lookup (d, key): se d e isinstance (d, dict): return d.get (key)
dalore

La creazione di una classe è troppo eccessiva; un dizionario meglio strutturato, combinato con la .itemschiamata (come illustrato in una delle altre risposte) è una soluzione molto più semplice.
Zags,

285
choices = {'key1':'val1', 'key2':'val2'}

Ecco il modello:

<ul>
{% for key, value in choices.items %} 
  <li>{{key}} - {{value}}</li>
{% endfor %}
</ul>

Fondamentalmente, .itemsè una parola chiave Django che divide un dizionario in un elenco di (key, value)coppie, proprio come il metodo Python .items(). Ciò consente l'iterazione su un dizionario in un modello Django.


@anacarolinats (e altri) assicurati solo di scorrere su entrambi la chiave, il valore delle scelte. Dovrebbe funzionare ancora.
OldTinfoil

Finalmente! Grazie!! : D
dj Grill,

quindi nel template engine non puoi usare (). BTW Grazie wotks per me.
BlaShadow

6
Bella soluzione concisa alla domanda. Per chiarire, itemsè una chiamata al metodo Python sul dizionario, non una parola chiave Django. Come sottolinea Alex Martelli, è praticamente lo stesso iteritems. Come ha risposto Wilhelm, la ricerca nel dizionario è terza in precedenza per le ricerche di punti. Se nel tuo dizionario hai un nome 'items', otterrai quel valore al posto di un elenco di tuple. Per testare: aggiungi {'items':'oops'}al tuo dizionario e otterrai un elenco puntato di lettere dalla parola 'oops'
cod3monk3y

1
Utilizzare collections.OrderedDict per controllare l'ordine dell'iterazione
dnalow

186

puoi usare la notazione punto:

Le ricerche di punti possono essere riassunte in questo modo: quando il sistema modello incontra un punto con un nome di variabile, prova le seguenti ricerche, in questo ordine:

  • Ricerca nel dizionario (ad es., Foo ["bar"])
  • Ricerca attributi (ad es. Foo.bar)
  • Chiamata al metodo (ad esempio, foo.bar ())
  • Ricerca indice-elenco (ad esempio, foo [2])

Il sistema utilizza il primo tipo di ricerca che funziona. È una logica di corto circuito.


44
Nel suo caso la scelta è una variabile. Fare .choice cercherà il valore per la chiave "scelta" piuttosto che il valore per la scelta chiave.
ibz,

+1 per le informazioni, anche se la domanda era una specie di domanda "indovina cosa sto pensando". Grazie Wilhelm.
eficker,

1
Funziona anche con dizionari nidificati. Codice Python: Codice my_dict[1][2]modello:my_dict.1.2
djsmith il

2
@ JCLeitão Perché la versione corretta è d.key.1- nota la seconda.
Izkata

3
Controlla i documenti su questo però ... da "1.6 docs.djangoproject.com/en/1.6/topics/templates/#variables ": nota che "bar" in un'espressione modello come {{foo.bar}} verrà interpretata come stringa letterale e non utilizzando il valore della variabile "bar", se ne esiste una nel contesto del modello.
Jamesc,

25

Devi trovare (o definire) un tag modello "get", ad esempio qui .

La definizione del tag:

@register.filter
def hash(h, key):
    return h[key]

Ed è usato come:

{% for o in objects %}
  <li>{{ dictionary|hash:o.id }}</li>
{% endfor %}

3
considerare a h.get(key,'default_value')causa di KeyError
semiomant

9

Usa elementi del dizionario:

{% for key, value in my_dictionay.items %}
  <li>{{ key }} : {{ value }}</li>
{% endfor %}


6

Simile alla risposta di @russian_spy:

<ul>
{% for choice in choices.items %} 
  <li>{{choice.0}} - {{choice.1}}</li>
{% endfor %}
</ul>

Questo potrebbe essere adatto per abbattere dizionari più complessi.


3

Idealmente, dovresti creare un metodo sull'oggetto di scelta che si è trovato nei voti o creare una relazione tra i modelli. Anche un tag modello che eseguiva la ricerca nel dizionario avrebbe funzionato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.