Dynamic title blocks not taken into account in pages.

My header.html is included in my base.html which is extended in all template pages.

header.html

{% block header %}
{% load static %}
{% load is_current %}
<!DOCTYPE html>
<html class="no-js" lang="fr">
   <head>
      <!--- basic page needs
         ================================================== -->
      <meta charset="utf-8">
      {% block title %}
      <title></title>
      {% endblock %}

   </head>
   <body id="top">
      <!-- header
         ================================================== -->
      <header class="s-header header">
         <!-- header_content -->
      </header>

{% endblock header %}

base.html

{% load static %}
{% block header %}
{% include 'header.html' %}
{% endblock header %}
{% block content %}
{% endblock %}
{% block footer %}
{% include 'footer.html' %}
{% endblock footer %}

For the header, I’ve tried multiple ways to load dynamic titles for each page.

This:

      {% block title %}
      <title></title>
      {% endblock %}

Or this:

      <title>
      {% block title %}
      {% endblock %}
      </title>

If I add a value to the title in header.html, it’s taken into account and it overrides all the title of inherited templates.

Example of inherited template:

{% extends 'base.html'%}
{% block title %} Some title {% endblock %}
{% load static %}
{% block content %}
<!-- some-content -->
{% endblock %}

Thanks for your help!

When you are “including” a template, you do not bracket that template with a block. The entire template is going to be inserted at the location of the include tag.

Also, see the note in the include docs regarding the context of included templates. Your block title isn’t going to work in the included file.

1 Like

Dear Ken,

Thanks for your kind reply.

I’ve indeed chosen to leave the template blocks method aside and rely on the class-based views, using this tutorial.

{{ Title }} in base.html (more precisely, in header.html included in base.html then extended in each template) :

<!doctype html>
<html lang="en">
<head>
    <title>{{ title }}</title>
</head>

Mixin for Class View to display dynamic titles:

class PageTitleViewMixin:
    title = ""

    def get_title(self):
        """
        Return the class title attr by default,
        but you can override this method to further customize
        """
        return self.title

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

Then in context, two options:

For static title, define the title after the template_name file reference:

    template_name = "example.html"
    title = "Example"

If we want to display a dynamic title for a blog post for instance, we need to return the title of our object.

    def get_title(self):
        return self.object.title

This works for my DetailView for one blog post.
However, when I want to define my title based on an object from a queryset, it fails.

  1. posts are filtered by tag from a queryset of tags
  2. tags are called in the model through TaggableManager with Django-Taggit
  3. I want to filter only the tags in model, not all the tags in the app
class PostListingByTag(PageTitleViewMixin, ListView):
    template_name = "tag.html"
    model = Tag
    tag = None
    object_list = X.objects.filter(status=1).order_by("-created_at")
    xy = object_list.filter(tags__in=[tag])

    print(tag_slug)
    def get_title(self):
        return self.object.title

    def PostsListForTag(request, tag_slug=None):
        print (slug)
        print(tag_slug)
        if tag_slug:
            tag = get_object_or_404(Tag, slug=tag_slug)
            xy = object_list.filter(tags__in=[tag])
            paginate_by = 4
            paginator = Paginator(xy, 4)
            page = request.GET.get('page')
            page_obj = paginator.get_page(page)  
            try:
                xy = paginator.page(page)
            except PageNotAnInteger:
                # If page is not an integer deliver the first page
                xy = paginator.page(1)
            except EmptyPage:
                # If page is out of range deliver last page of results
                xy = paginator.page(paginator.num_pages)
            return render(request,
                        'tag.html',
                        {
                        'page_obj': page_obj,
                        'xy': xy,
                        'tag': tag
                        })

Here are the fields for the Tag model: article, id, name, num_times, slug, taggit_taggeditem_items, post.

What am I doing wrong here?
If needed, I can submit another request in a new post.

Thanks a lot!

A ListView works with a list (queryset), not with an individual object. There is no self.object that gets populated within a ListView, and so your get_title function will not work in that class. If you want to set the title from within that view, you either need to identify the title directly or by selecting an element from within the queryset.