Search code examples
djangodjango-templatesdjango-orm

Relational queryset not showing properly in template


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)

Output


Solution

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