views:

48

answers:

3

I have the following models:

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)

In a view I create a list of Entry object and want to show the elements in the template:

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

And with this template code it generates the following TemplateSyntaxError pointing to the template's first line (for tag):

Caught TypeError while rendering: 'ManyRelatedManager' object is not iterable

The entries variable is a list:

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

Do you know what can be the problem here and how to resolve this issue?

I'm new to Django, so any suggestions how to debug the templates may be helpful.

Update

I get the same error even with this template:

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

There is no need to turn the entries QuerySet into a list. Additionally, you can let the DB do the sorting using order_by.

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

Add .all to get all the values from a relationship (just like Entry.objects.all()).

entry.tags.all

You can try this in the shell as well (I use ipython so your output may look different):

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

And if you want to call out the entries with zero tags use for..empty.

{% for tag in entry.tags.all %}
    {{ tag.name }}
{% empty %}
    No tags!
{% endfor %}
istruble
Actually I have already tried adding .all. But in the template side I get en empty list.
grigy
Updated the shell code to make sure at least one entry has a tag. Added a template example using for..empty to show a way to indicate that there were no tags.
istruble
The problem is that it works in shell. But in the template I get nothing, though the entires contains elements.
grigy
Please see my update at the bottom of the question
grigy
If you are still doing your list(...) stuff, then make sure you do not add .all in the template. Also, try adding your view code to the question. Or maybe just add `import pdb; pdb.set_trace()` in the view and take a look at the variables you have. Alternatively you can try looking at the variables with the django-debug-toolbar http://github.com/robhudson/django-debug-toolbar
istruble
Thanks for the tips.
grigy
+1  A: 

The above from istruble is correct but if your question contains all of your code you need to specify a property in your template:

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

or a default unicode function to your model:

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

OK. I found the problem. I had some incorrect code which was commented out. But Django processed that code. So html comments didn't work here. I fixed this and it all worked like a charm.

So if you didn't know - the html comments don't prevent template processing.

This is because the template is being processed by Django first then HTML is rendered by browser.

grigy
You will probably enjoy {# onliner comment #} and {% comment %} ... {% endcomment %}. http://docs.djangoproject.com/en/dev/ref/templates/builtins/#comment
istruble
Yes. Thank you!
grigy