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

в представлении я создаю список объектов ввода и хочу показать элементы в шаблоне:

   {% 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 %}

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..пусто.

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

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

проверка вашего решения, приведя пример

предположим, что книга имеет количество тегов, поэтому для отображения всех тегов книги по шаблону может быть так:

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

где модель тег вроде

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

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

OK. Я нашел проблему. У меня был неправильный код, который был прокомментирован. Но Джанго обработал этот код. Поэтому HTML-комментарии здесь не работали. Я исправил это, и все сработало как по волшебству.

Итак, если вы не знали - HTML-комментарии не препятствуют обработке шаблонов.

Это потому, что шаблон обрабатывается Django сначала, а затем HTML визуализируется браузером.


вышеизложенное из 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