I believe is a quite basic problem, but I'm trying to render in a template all the titles for an specific page, and inside that title its corresponding text. With these models:
class Page(models.Model):
page_title = models.CharField(_("title of the page"), max_length=50)
category = models.ForeignKey('Category', on_delete=models.CASCADE)
def __str__(self):
return self.page_title
class Category(models.Model):
category_name = models.CharField(_("name of the category"), max_length=50)
def __str__(self):
return self.category_name
class Title(models.Model):
title = models.CharField(_("titulo"), max_length=50)
page = models.ForeignKey(Page, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Text(models.Model):
title = models.ForeignKey(Title, verbose_name=_("titulo de la pagina a la que pertenece"), on_delete=models.CASCADE, default='')
content = models.TextField()
def __str__(self):
return f"{self.title}"
I am using this view to render the logic:
def index(request):
pages = Page.objects.all()
titles = Title.objects.filter(page__id=2)
for title in titles:
title_id = title.id
texts = Text.objects.filter(title__id=title_id)
context = {
'pages' : pages,
'titles' : titles,
'texts' : texts,
}
return render(request, 'index.html', context)
But with this approach the texts
only gives me the text of the last title when rendered this way in template:
{% for page in pages %}
<h1>{{page}}</h1>
{% for title in titles %}
<h3>{{title}}</h3>
{% for text in texts %}
<p>{{text}}</p>
{% endfor %}
{% endfor %}
{% endfor %}
The desired rendering would be all the titles and texts were displayed like this:
Title 1
Text of title 1
Title 2
Text of title 2
Title 3
Text of title 3
For as many titles and texts there are in the database. What would be the approach for that?
Edit: the current output shows the titles correctly but the text is always the last one (in this case text 3)
CodePudding user response:
The problem is in the views logic:
try this:
def index(request):
pages = Page.objects.all()
titles = Title.objects.filter(page__id=2)
title_id = []
for title in titles:
title_id.append(title.id)
texts = Text.objects.filter(title__id__in=title_id)
context = {
'pages' : pages,
'texts' : texts,
}
return render(request, 'index.html', context)
Also in models.py
change class Text
as:
class Text(models.Model):
title = models.ForeignKey(Title, verbose_name="titulo de la pagina a la que pertenece", on_delete=models.CASCADE, default='')
content = models.TextField()
def __str__(self):
return self.content #here
Then in template do this:
{% for page in pages %}
<h1>{{page}}</h1>
{{texts}}
{% for text in texts %}
<h3>{{text.title}}</h3>
<p>{{text}}</p>
{% endfor %}
{% endfor %}
Hope this will work !
CodePudding user response:
The answer was simple as I was iterating wrong in the template. I had to use _set.all
in order to retrieve the correct child elements.
{% for page in pages %}
<h1>{{page}}</h1>
{% for title in titles %}
<h3>{{title}}</h3>
{% for text in title.text_set.all %} # This
<p>{{text.content}}</p>
{% endfor %}
{% endfor %}
{% endfor %}