2008-11-07 16 views
44

Dans mon views.py, je construis une liste de deux-tuples, où le deuxième élément dans le tuple est une autre liste, comme ceci:Django - Comment faire un tuple déballage dans un modèle 'for' boucle

[ Product_Type_1, [ product_1, product_2 ], 
    Product_Type_2, [ product_3, product_4 ]] 

dans le vieux Python ordinaire, je pourrais l'itération la liste comme ceci:

for product_type, products in list: 
    print product_type 
    for product in products: 
     print product 

Je ne peux pas sembler faire la même chose dans mon modèle Django:

{% for product_type, products in product_list %} 
    print product_type 
    {% for product in products %} 
     print product 
    {% endfor %} 
{% endfor %} 

Je reçois cette erreur de Django:

Caught une exception tout en rendant: Argument # 2 zip doit prendre en charge l'itération

Bien sûr, il y a quelques balises HTML dans le modèle, ne pas imprimer des relevés. Le déballage de tuple n'est-il pas pris en charge dans la langue du modèle Django? Ou est-ce que je vais à ce sujet dans le mauvais sens? Tout ce que j'essaie de faire est d'afficher une simple hiérarchie d'objets - il existe plusieurs types de produits, chacun avec plusieurs produits (dans models.py, Product a une clé étrangère à Product_type, une simple relation un-à-plusieurs).

De toute évidence, je suis assez nouveau à Django, donc toute contribution serait appréciée.

+2

Vous parlez de tuples, mais votre question contient seulement des listes. Ce sont des choses différentes en python. –

+0

Vous n'avez actuellement pas deux tuples. Regardez attentivement votre liste, vous avez 4 éléments de la liste. Comme Jonny Buchanan note, vous devez faire ceci: [[Product_Type_1, [product_1, product_2],], [Product_Type_2, [product_3, product_4],],] pour obtenir une version de liste de deux triplets. – MontyThreeCard

Répondre

53

ce serait mieux si vous construisez vos données comme {note le « (» et «) » peuvent être échangés contre « [ » et « ] » repectively, un être pour tuples, un pour les listes}

[ (Product_Type_1, (product_1, product_2)), 
    (Product_Type_2, (product_3, product_4)) ] 

et ont le modèle faire:

{% for product_type, products in product_type_list %} 
    {{ product_type }} 
    {% for product in products %} 
     {{ product }} 
    {% endfor %} 
{% endfor %} 

les tuples/listes sont ainsi déballés dans des boucles est basée sur l'article retourné par la liste iterator. chaque itération seulement un élément a été retourné. la première fois autour de la boucle, Product_Type_1, la deuxième liste de produits ...

+1

Vous pensiez que vous construisiez une liste de deux-tuples, mais vous avez oublié la partie tuple - notez les parenthèses supplémentaires entourant les paires de type produit/liste de produits dans la réponse Cipher –

+0

Cela ne fonctionne pas pour les anciennes versions de Django (comme celle utilisée dans le GAE). Utilisez la réponse d'Ashwin Rao si vous obtenez cette erreur: "pour" les déclarations avec cinq mots devraient se terminer par "inversé" " –

2

Il suffit d'envoyer le modèle une liste des types de produits et de faire quelque chose comme:

{% for product_type in product_type_list %} 
    {{ product_type }} 
    {% for product in product_type.products.all %} 
     {{ product }} 
    {% endfor %} 
{% endfor %} 

Il a été un peu alors que je ne peux pas me rappeler exactement ce que la syntaxe est, laissez-moi savoir si cela fonctionne. Vérifiez le .

+0

+1: ne pas sur-traiter dans la vue –

+0

Chris Lawlor n'a pas expliqué comment il s'est retrouvé avec la structure de données qu'il possède (qui n'est pas réellement une liste de deux-tuples), mais cette approche suggérée aboutirait à: N + 1 requêtes pour afficher la liste des produits. –

+0

Voici des dragons. En utilisant cette suggestion, vous effectuez un déplacement distinct dans la base de données pour chaque type de produit. Je soupçonne que la minimisation de la charge de la base de données est probablement la motivation derrière l'utilisation des tuples en premier lieu. – btubbs

5

Vous devez utiliser cette façon:

{% for product_type, products in product_list.items %} 
    print product_type 
    {% for product in products %} 
     print product 
    {% endfor %} 
{% endfor %} 

Ne pas oublier les éléments variables dans les données du dictionnaire

+0

Enfin, la réponse que je cherchais. Je vous remercie! – Teekin

57

Une autre façon est la suivante.

Si on a une liste de tuples dire

mylst = [(a, b, c), (x, y, z), (l, m, n)], 

alors on peut déballer cette liste dans le fichier modèle de la manière suivante. Dans mon cas, j'avais une liste de tuples qui contenait l'URL, le titre et le résumé d'un document.

{\% for item in mylst \%}  
    {{ item.0 }} {{ item.1}} {{ item.2 }}  
{\% endfor \%} 
+0

C'est exactement ce que je cherchais, merci. – mlsteeves

+4

'.0' ... pas intuitif du tout. –

+0

@iuliux astuce est de se rappeler que le langage de template fait '.' signifiera n'importe quoi de l'accès variable à l'abonnement, en passant par l'invocation de méthode, tous avec la même syntaxe ... Toujours d'accord avec vous, :) – mccc

1

Si vous avez un nombre fixe dans vos tuples, vous pouvez simplement utiliser l'indexation.Je avais besoin de mélanger un dictionnaire et les valeurs étaient tuples, donc je l'ai fait:

De l'avis:

my_dict = {'parrot': ('dead', 'stone'), 'lumberjack': ('sleep_all_night', 'work_all_day')} 

Dans le modèle:

<select> 
    {% for key, tuple in my_dict.items %} 
    <option value="{{ key }}" important-attr="{{ tuple.0 }}">{{ tuple.1 }}</option> 
    {% endfor %} 
</select>