Как вывести список объектов, содержащих отношения «многие ко многим» в шаблоне 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 = 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 в список. Кроме того, вы можете позволить БД выполнять сортировку с помощью 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
Проблема в том, что он работает в оболочке. Но в шаблоне я ничего не получаю, хотя entires содержит элементы. - person grigy; 23.10.2010
comment
Если вы все еще занимаетесь списком (...), убедитесь, что вы не добавили .all в шаблон. Также попробуйте добавить в вопрос свой код представления. Или, может быть, просто добавьте import pdb; pdb.set_trace() в представление и посмотрите на имеющиеся у вас переменные. В качестве альтернативы вы можете попробовать просмотреть переменные с помощью панели инструментов django-debug 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

OK. Я нашел проблему. У меня был некорректный код, который был закомментирован. Но 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