One of the basic principles in programming is code reusing. There is a good chance you'll have some identical parts of code for different pages. Making a website with tens or hundreds of pages will cause you to do a lot of copy-pasting. How to avoid it? With the power of Django template inheritance, you can define sections on a separate template and use them inside other templates.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
]Include
Our blogger friend John Doe needs some help with the blog: he wants to show his contacts in each post. We create a simple template in the file blog/templates/blog/contacts.html for the contacts section on a page:
<table>
<tr>
<td>Phone:</td>
<td>0-123-456-7890</td>
</tr>
<tr>
<td>Email:</td>
<td>[email protected]</td>
<tr>
</table>To include it in any other template, we can use the {% include %} tag:
<!-- some content -->
{% include "blog/contacts.html" %}
<!-- some content -->This way, we don't need to copy the same code with contacts repeatedly; we simply include it. If we ever want to change what the contacts look like, we need to change the contacts.html file, and all other templates will have the updated contacts right away.
Creating and extending a template
You know how to include predefined parts to create a new template. Once you start using this method, you'll probably notice that the includes are repeating across different templates. Our goal was to minimize repetition, but it's still there. To solve this problem, let's define the base template, extend it, and populate only the different parts.
As a rule, all HTML pages for a particular site have much in common. If you don't want to repeat the same code repeatedly, you can slice your template into several blocks and then redefine only the blocks you need (and not redefine if you don't need them).
Let's make the base template in the file blog/templates/blog/base.html with the title and content blocks in it:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Genius blog</title>
</head>
<body>
<!-- main section starts -->
<main>
{% block content %}
{% endblock %}
</main>
<!-- main section ends -->
</body>
</html>{% block content %} {% endblock%} in the main HTML tags create a section with your content. This HTML content comes from another template that extends the base.html template. Blocks allow you to replace things based on inheritance.
To extend a template when you use its code as a layout, structure, or base for multiple templates, create the articles.html file in blog/templates/blog. Paste this template to blog/templates/blog/articles.html:
{% extends 'blog/base.html' %}
<!— base.html block content goes below -->
{% block content %}
<h2>Welcome to genius blog page</h2>
{% endblock %}{% extends 'blog/base.html' %} uses the base.html file as a layout or a base template; it also renders the block content in articles.html.
Your base.html file becomes the parent template, while articles.html becomes the child template. Anything you want to add in a child template should be within blocks({% block content %} {% endblock %}), which Django uses to populate the parent.
Note that {% block content %} must be the same name as the one used in your base.html template. For example, if you use {% block body %} inside your base template, it means that {% block body %} must be used in your articles.html template. You can extend base.html with multiple HTML templates.
Using templates in other templates
You can use include templates with multiple HTML templates. Let's look at how to make your form template appear on the contact page by extending your base template. We're assuming that you already have an HTML template ready called form.html.
Create a form template.
Extend your base template inside the contact.html file
Include your form template within the
{% block %}{% endblock %}tag
Here is an example:
blog/templates/blog/contact.html:
{% extends 'blog/base.html' %}
<!— base.html block content goes below -->
{% block content %}
<h2>Contact page</h2>
<!— include your form template below -->
{% include 'blog/form.html' %}
{% endblock %}Everything you want to include must be within blocks Django uses to populate the parent when extending a template.
Rendering your home template to the browser
Suppose you have successfully created your base and navbar template; it's time to build your home template. Open your blog/views.py. You need to add a view function:
from django.shortcuts import render
def home(request):
return render(request, "blog/home.html")After this, create URLs in a new Python file in your blog app. Name it urls.py and add the following code to your blog/urls.py:
from django.urls import path
from .views import home
urlpatterns = [
path('', home, name='home'),
]Next, you must include the url.py blog app file in the project urls.py file. Copy this to project/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
]Time to build your home.html template! Copy this template to blog/templates/blog/home.html:
{% extends 'blog/base.html' %}
<!-- base.html block content goes below -->
{% block content %}
<h2>Genius blog homepage</h2>
{% endblock %}After this, you can start the project server and visit http://127.0.0.1:8000 in your browser.
Note that your base template can have more than one block; it's common for them to have a lot of blocks.
Extending admin page
Another way to use the template extension is to extend the default admin page. This allows you to customize the data display in the admin panel, tailoring it to the needs of our application. It gives us complete control over the admin panel's data display and interface elements.
Creating templates with the same names as standard Django admin templates would be best. By default, admin templates are in the admin/app_name/model_name/ directory. You need to create a new templates/admin folder inside your application and create a base_site.html file. In this file, you will define your base template for the admin page.
{% extends "admin/base.html" %}
{% block extrahead %}
<!-- Here you can add your scripts and styles -->
{% endblock %}
{% block content %}
<!-- Here you can add your own content -->
{% endblock %}So far, there is no strict need to customize the administrative panel for our tasks. However, knowledge about this may be helpful to us in the future.
Conclusion
Django template inheritance provides the following tools:
{% include %}to load a section of code within the framework of another template;{% extends %}to extend a template when you need to use its code as a base for multiple templates;{% block %}{% endblock %}to define sections in your base template. Blocks allow you to replace items based on inheritance.
Template inheritance helps you define sections on a separate template and reuse them inside other templates. It saves you from much copy-pasting and applies the don't repeat yourself (DRY) principle.