2010-10-22 4 views
9

Je les modèles suivants:Comment afficher une liste d'objets contenant des relations many-to-many dans le template Django?

class Tag(models.Model): 
    name = models.CharField(max_length=20) 

class Entry(models.Model): 
    title = models.CharField(max_length=100) 
    date = models.DateField() 
    tags = models.ManyToManyField(Tag) 

Dans une vue que je crée une liste d'objets d'entrée et que vous souhaitez afficher les éléments du modèle:

{% for entry in entries %} 
    {{ entry.title }} 
    {{ entry.date }} 
    <!-- {% for tag in entry.tags %} {{ tag }} {% endfor %} --> 
    {% endfor %} 

Et avec ce code modèle génère le suivant TemplateSyntaxError pointe vers la première ligne du modèle (pour la balise):

Pris TypeError tout en rendant: objet « ManyRelatedManager » est pas itérables

La variable entrées est une liste:

entries = Entry.objects.filter(user=user_id) 
entries = list(entries) 
entries.sort(key=lambda x: x.id, reverse=False) 

Savez-vous ce qui peut être ici le problème et comment résoudre ce problème? Je ne connais pas encore Django, donc les suggestions pour déboguer les modèles peuvent être utiles.

Mise à jour

je reçois la même erreur, même avec ce modèle:

{% for entry in entries.all %} 
<!-- everything is commented out here --> 
{% endfor %} 
+2

Pourquoi êtes-vous convertir des 'entrées' en une liste et le trier en Python? C'est très inefficace. Vous devriez utiliser 'order_by' pour obtenir la base de données pour faire le tri. –

+0

Bonne prise. Merci! – grigy

Répondre

37

Il n'y a pas besoin de tourner les entrées QuerySet dans une liste. De plus, vous pouvez laisser le DB effectuer le tri en utilisant order_by.

entries = Entry.objects.filter(user_id=user_id).order_by('id') 

Ajouter .all pour obtenir toutes les valeurs d'une relation (comme Entry.objects.all()).

entry.tags.all 

Vous pouvez essayer cela dans la coquille aussi bien (je l'utilise ipython de sorte que votre sortie peut être différent):

$ ./manage.py shell 
# ... 
In [1]: from yourproject.models import Entry, Tags 
In [2]: entry = Entry.objects.all()[0] 
In [3]: entry.tags 
Out[3]: <django.db.models.fields.related.ManyRelatedManager object at 0x...> 
In [4]: entry.tags.all() # for an entry with no tags. 
Out[4]: [] 
In [5]: # add a few tags 
In [6]: for n in ('bodywork', 'happy', 'muscles'): 
    ...:  t, created = Tag.objects.get_or_create(name=n) 
    ...:  entry.tags.add(t) 
In [7]: entry.tags.all() 
Out[7]: [<Tag: ...>, <Tag: ...>, <Tag: ...>] 

Et si vous voulez appeler les entrées avec zéro balises utiliser for..empty.

{% for tag in entry.tags.all %} 
    {{ tag.name }} 
{% empty %} 
    No tags! 
{% endfor %} 
+0

En fait, j'ai déjà essayé d'ajouter .all. Mais dans le côté du modèle, je reçois une liste vide. – grigy

+0

Mise à jour du code du shell pour s'assurer qu'au moins une entrée possède un tag. Ajout d'un exemple de modèle utilisant for..empty pour montrer un moyen d'indiquer qu'il n'y avait pas de balises. – istruble

+0

Le problème est que cela fonctionne dans shell. Mais dans le gabarit, je n'ai rien, bien que les entires contiennent des éléments. – grigy

3

Le ci-dessus de istruble est correct, mais si votre question contient tous votre code, vous devez spécifier une propriété dans votre modèle:

{% for entry in entries %} 
    {{ entry.title }} 
    {{ entry.date }} 
    {% for tag in entry.tags.all %} {{ tag.name }} {% endfor %} 
    {% endfor %} 

ou une fonction par défaut unicode à votre modèle:

class Tag(models.Model): 
    name = models.CharField(max_length=20) 
    def __unicode__(self): 
     return self.name 
4

OK. J'ai trouvé le problème. J'ai eu un code incorrect qui a été commenté. Mais Django a traité ce code. Donc, les commentaires html n'ont pas fonctionné ici. J'ai réparé ceci et tout a fonctionné comme un charme. Donc, si vous ne le saviez pas, les commentaires html n'empêchent pas le traitement des modèles . Ceci est dû au fait que le modèle est en cours de traitement par Django, puis le HTML est rendu par le navigateur.

+6

Vous apprécierez probablement {# onliner comment #} et {% comment%} ... {% endcomment%}. http://docs.djangoproject.com/fr/dev/ref/templates/builtins/#comment – istruble

+0

Oui. Je vous remercie! – grigy

6

Voici la solution de votre requête,

Vérification de votre solution en donnant un exemple

Supposons un livre ont nombre d'étiquettes, de sorte afin d'afficher toutes les balises d'un livre sur le modèle peut être comme celui-ci

{% for tag in book.tags.all %} 
    {{ tag.name }} 
{% endfor %} 

où le modèle de Tag est comme,

class Tag(models.Model): 
    name = models.CharField(max_length=100) 

    def __unicode__(self): 
    return "%s" % unicode(self.name) 
Questions connexes