Display categories and associated items on one page

I created tree-based model of categories with django-mptt and added a few test items to them. I use templates and can display on one page categories or items. Can i display categories and associated items on one page? For example, I made some drawings about the situation.


Sure! Pretty much you can display any data on a page that you can create a view to retrieve.

You are not limited to rendering one list or queryset in a template. You create your context with all the data on the page that you want, then you render that data in the template.

Everything else is just an issue of doing the layout in terms of html and css.

I understand this, but I can’t find how to do it. I tried to merge the two views by creating a third one. After that, I made new template where i called that view. But that didn’t work.
Maybe you know an easy way and can give me a hint?

You already know how to retrieve data from the database, create a context from that data, then render a result.

Why don’t you post your attempt and we can work forward from there?

My only suggestion for this is that you start simple. If you’re wrestling with the idea of rendering two different querysets in the same view, then pick two different simple querysets to start with.

Also, you haven’t mentioned whether you’re trying to do this in an FBV or a CBV. I’ll take this opportunity to point out that the Django-provided generic CBVs are heavily oriented toward representations of single querysets only. If you’re working with multiple querysets, I wouldn’t suggest trying to build your view on anything more than the generic View class (or more likely, TemplateView). The more sophisticated views such as ListView, UpdateView, etc, are not necessarily the best “fit” for something like this if you’re wanting to do anything other than just displaying the data from those other models.

I use CBV. They work well if I use them separately. But I tried make FBV for merge them.

class CategoryListView(ListView):
    model = Category
    template_name = "category_list.html"

class LinkByCategoryView(ListView):
    context_object_name = 'links'
    template_name = 'link_list.html'

    def get_queryset(self):
        self.category = Category.objects.get(slug=self.kwargs['slug'])
        queryset = Link.objects.filter(category=self.category)
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = self.category
        return context

def category_and_links(request, category_slug):
    # FBV for merge
    category_view = CategoryDetailView.as_view()(request, slug=category_slug)
    link_view = LinkByCategoryView.as_view()(request, category_slug=category_slug)
    return render(request, 'test.html', {
        'category_view': category_view,
        'link_view': link_view,

There`re templates:

# category_list.html

{% extends "base.html" %}

{% load mptt_tags %}

{% block title %}Home{% endblock %}

{% block content %}

	<h3>My collections</h3>
	{% recursetree object_list %}
		<a href="{{node.get_absolute_url}}" title="{{node.get_absolute_url}}">{{node.name}}</a>
		{% if not node.is_leaf_node %}
                <ul class="children">
                    {{ children }}
		{% endif %}
	{% endrecursetree %}

{% endblock %}

# link_list.html

{% extends "base.html" %}
{% block title %}Links from {{title}}{% endblock %}

{% block content1 %}
	<div class="container">
	    <h1>Links in {{title}}</h1>
		{% for link in object_list%}
			<a href="{{link.slug}}" title="{{link.slug}}">{{link.name}}</a>
		{% endfor %}
{% endblock %}

# and test.html where i try merge views

{% extends "base.html" %}

{% block content %}
    {{ category_view }}
{% endblock%}

{% block content1 %}
    {{ link_view }}
{% endblock%}

So the issue here is that you’re trying to iterate over the default context name used by the CBVs (object_list).

You need to iterate over the names of the objects as you have them defined in the context (category_view and link_view).

Spinoff question, Im sorry.
Is having both get_queryset and get_context_data redundant or okay in a cbv?

Actually, having both is quite appropriate in many circumstances. Their intent is to satisfy two separate and distinct functional requirements within the CBV.

Every “higher level” CBV (e.g. ListView, CreateView, UpdateView, DetailView) is designed around the idea of handling one Model (ListView) or Object (the others).
The purpose of get_queryset and get_object is to retrieve the data related to that entity.

The purpose of get_context_data is to retrieve all other data you may wish to use in those views.

So get_context_data calls get_queryset (implicitly) if that is not defined?

No, they’re two separate and independent functions. They do two different things.

There’s no such thing as either of them not being defined - they’re both defined in the base CBV classes.

This is model.py:

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

def __str__(self):
    return self.name

class Post(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, default=‘car’)

This is views.py:

def home(request):
context = {
‘posts’: Post.objects.all(),
‘categories’: Category.objects.all()
return render(request, ‘core/home.html’, context)

this is home.html:

{% for category in categories %}
  <p>{{ category.name }}</p>
{% endfor %}

WHEN I RUNSERVER IT DOESNT SHOW NEITHER THE “TEST” OR any categories i have in my django admin site.(categories exists–> >>> Category.objects.all()
<QuerySet [<Category: Motorcycles>, <Category: Job>, <Category: car>, <Category: Property>]>


Please open a new topic for your discussion.

Include all this information, including clarification as to whether you’re talking about your view or the admin. (Your post isn’t clear on that.)

Also, when you’re posting code or templates here, surround the code between lines of three backtick - ` characters. This means you’ll have a line of ```, then your code, then another line of ```.