Как да покажа списък с обекти, съдържащи релации много към много в 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)

В изглед създавам списък с обект Entry и искам да покажа елементите в шаблона:

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

И с този код на шаблона той генерира следния TemplateSyntaxError, сочещ към първия ред на шаблона (за етикет):

Уловена TypeError по време на изобразяване: обектът „ManyRelatedManager“ не може да се повтаря

Променливата entries е списък:

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

Знаете ли какъв може да е проблемът тук и как да го разрешите?

Аз съм нов в Django, така че всякакви предложения как да отстранявам грешки в шаблоните може да са полезни.

Актуализация

Получавам същата грешка дори с този шаблон:

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

person grigy    schedule 22.10.2010    source източник
comment
Защо преобразувате „записи“ в списък и го сортирате в Python? Това е много неефективно. Трябва да използвате „order_by“, за да накарате базата данни да извърши сортирането.   -  person Daniel Roseman    schedule 22.10.2010


Отговори (4)


Няма нужда да превръщате записите QuerySet в списък. Освен това можете да позволите на DB да извърши сортирането с помощта на order_by.

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

Добавете .all, за да получите всички стойности от връзка (точно като Entry.objects.all()).

entry.tags.all

Можете да опитате това и в обвивката (аз използвам ipython, така че изходът ви може да изглежда различно):

$ ./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: ...>]

И ако искате да извикате записите с нулеви тагове, използвайте за ..празен.

{% for tag in entry.tags.all %}
    {{ tag.name }}
{% empty %}
    No tags!
{% endfor %}
person istruble    schedule 22.10.2010
comment
Всъщност вече се опитах да добавя .all. Но в страната на шаблона получавам празен списък. - person grigy; 22.10.2010
comment
Актуализирах шел кода, за да се уверя, че поне един запис има етикет. Добавен е пример за шаблон, използващ for..empty, за да покаже начин да се покаже, че няма етикети. - person istruble; 22.10.2010
comment
Проблемът е, че работи в shell. Но в шаблона не получавам нищо, въпреки че целият съдържа елементи. - person grigy; 23.10.2010
comment
Ако все още правите вашите списък(...) неща, тогава се уверете, че не добавяте .all в шаблона. Освен това опитайте да добавите своя код за изглед към въпроса. Или може би просто добавете import pdb; pdb.set_trace() в изгледа и погледнете променливите, които имате. Като алтернатива можете да опитате да разгледате променливите с django-debug-toolbar github.com/robhudson/django -debug-toolbar - person istruble; 23.10.2010
comment
най-добрата идея, спаси ми деня. - person Ali Akhtari; 06.08.2019

Ето решението на вашето запитване,

Проверка на вашето решение чрез даване на пример

Да предположим, че една книга има няколко тагове, така че за да се покажат всички тагове на книга в шаблон може да бъде така

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

където моделът на Tag е като,

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

    def __unicode__(self):
    return "%s" % unicode(self.name)
person Anupam Shakya    schedule 16.05.2013

ДОБРЕ. Открих проблема. Имах някакъв неправилен код, който беше коментиран. Но Django обработи този код. Така че html коментарите не работят тук. Поправих това и всичко заработи като чар.

Така че, ако не сте знаели - HTML коментарите не пречат на обработката на шаблон.

Това е така, защото шаблонът се обработва първо от Django, след което HTML се изобразява от браузъра.

person grigy    schedule 22.10.2010
comment
Вероятно ще се насладите на {# onliner comment #} и {% comment %} ... {% endcomment %}. docs.djangoproject.com/en/dev/ref/templates/builtins /#коментар - person istruble; 23.10.2010

Горното от istruble е правилно, но ако въпросът ви съдържа целия ви код, трябва да посочите свойство във вашия шаблон:

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

или функция по подразбиране unicode за вашия модел:

class Tag(models.Model):
  name = models.CharField(max_length=20)
  def __unicode__(self):
      return self.name
person sunn0    schedule 22.10.2010