{"id":1742,"date":"2026-09-26T06:04:19","date_gmt":"2026-09-26T06:04:19","guid":{"rendered":"https:\/\/nayananimsara.online\/?p=1742"},"modified":"2026-09-27T05:41:56","modified_gmt":"2026-09-27T05:41:56","slug":"django-template-language-explained-pt1","status":"publish","type":"post","link":"https:\/\/nayananimsara.online\/django-template-language-explained-pt1\/","title":{"rendered":"Django Template Language (DTL) Explained: Part 1 for Beginners"},"content":{"rendered":"\n<h1 id=\"django-template-language-dtl-explained-part-1-for-beginners\" class=\"wp-block-heading\">Django Template Language (DTL) Explained: Part 1 for Beginners<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Django Template Language Explained, Every view built so far in this course has had the same problem buried inside it. The homepage, the About page, the blog post view \u2014 each one carries a full copy of the same navbar, the same <code>&lt;!DOCTYPE html&gt;<\/code>, the same closing tags, all sitting inside a Python string. Add a tenth page, and you&#8217;re maintaining ten near-identical copies of that boilerplate. Change one word in the nav, and you&#8217;re editing ten files by hand.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s the exact problem Django&#8217;s template system was built to solve. This is where the course actually gets to use it.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"418\" height=\"644\" src=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-20.png\" alt=\"Django Template Language Explained\" class=\"wp-image-1743\" srcset=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-20.png 418w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-20-195x300.png 195w\" sizes=\"(max-width: 418px) 100vw, 418px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table of Contents<\/h2><nav><ul><li><a href=\"#django-template-language-dtl-explained-part-1-for-beginners\">Django Template Language (DTL) Explained: Part 1 for Beginners<\/a><ul><li><a href=\"#what-a-template-actually-is-django-template-language-explained\">What a Template Actually Is (Django Template Language Explained)<\/a><\/li><li><a href=\"#step-1-setting-up-a-templates-folder\">Step 1: Setting Up a Templates Folder<\/a><\/li><li><a href=\"#step-2-moving-html-out-of-the-view\">Step 2: Moving HTML Out of the View<\/a><\/li><li><a href=\"#step-3-rendering-the-template-from-a-view\">Step 3: Rendering the Template From a View<\/a><\/li><li><a href=\"#step-4-displaying-a-variable-with-dtl\">Step 4: Displaying a Variable With DTL<\/a><\/li><li><a href=\"#try-it-with-a-second-variable\">Try It With a Second Variable<\/a><\/li><li><a href=\"#what-hasnt-been-covered-yet\">What Hasn&#8217;t Been Covered Yet<\/a><\/li><li><a href=\"#a-mistake-worth-flagging-early\">A Mistake Worth Flagging Early<\/a><\/li><li><a href=\"#series-connections\">Series Connections<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n\n\n<h2 id=\"what-a-template-actually-is-django-template-language-explained\" class=\"wp-block-heading\">What a Template Actually Is (Django Template Language Explained)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A template is just an HTML file that Django can fill in with data at the moment a page is requested, instead of that HTML living as a string inside a Python function. Django&#8217;s Template Language, usually shortened to DTL, is the small set of syntax rules that let a plain HTML file do things a plain HTML file normally can&#8217;t \u2014 starting, in this lesson, with displaying a value passed in from a view.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It&#8217;s not a new programming language to learn from scratch. It&#8217;s a fairly small vocabulary layered on top of HTML, and Part 1 only covers the first piece of it.<\/p>\n\n\n\n<h2 id=\"step-1-setting-up-a-templates-folder\" class=\"wp-block-heading\">Step 1: Setting Up a Templates Folder<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Django looks for templates in a specific place. Inside your app, create this structure:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>blog\/\n    templates\/\n        blog\/\n            home.html<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"313\" height=\"242\" src=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-21.png\" alt=\"Django Template Language Explained\" class=\"wp-image-1744\" srcset=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-21.png 313w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-21-300x232.png 300w\" sizes=\"(max-width: 313px) 100vw, 313px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">That nested blog folder inside <code>templates<\/code> looks redundant at first, but it exists to prevent naming collisions \u2014 if two different apps both have a <code>home.html<\/code>, this structure keeps them from overwriting each other in Django&#8217;s lookup.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then check <code>settings.py<\/code>. By default, Django&#8217;s <code>startproject<\/code> command already configures the <code>TEMPLATES<\/code> setting to search inside each app&#8217;s <code>templates<\/code> folder automatically, so in most cases nothing needs to change here \u2014 it&#8217;s just worth knowing this is the setting that makes the folder structure above actually work.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"801\" height=\"400\" src=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-22.png\" alt=\"Django Template Language Explained\" class=\"wp-image-1745\" srcset=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-22.png 801w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-22-300x150.png 300w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-22-767x383.png 767w\" sizes=\"(max-width: 801px) 100vw, 801px\" \/><\/figure>\n\n\n\n<h2 id=\"step-2-moving-html-out-of-the-view\" class=\"wp-block-heading\">Step 2: Moving HTML Out of the View<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Take the homepage HTML you&#8217;ve been building through <code>HttpResponse<\/code> and move it into <code>home.html<\/code> almost exactly as it was:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">html<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;title&gt;My Django Site&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;nav&gt;\n        &lt;a href=\"\/\"&gt;Home&lt;\/a&gt;\n        &lt;a href=\"\/about\/\"&gt;About&lt;\/a&gt;\n    &lt;\/nav&gt;\n\n    &lt;main&gt;\n        &lt;h1&gt;Welcome to my site&lt;\/h1&gt;\n        &lt;p&gt;This homepage is now rendered from a real template file.&lt;\/p&gt;\n    &lt;\/main&gt;\n\n    &lt;footer&gt;\n        &lt;p&gt;&amp;copy; 2026 My Django Site&lt;\/p&gt;\n    &lt;\/footer&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"592\" src=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-23-1024x592.png\" alt=\"Django Template Language Explained\" class=\"wp-image-1746\" srcset=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-23-1024x592.png 1024w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-23-300x173.png 300w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-23-767x443.png 767w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-23.png 1255w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Notice this is plain HTML right now \u2014 no DTL syntax yet. That&#8217;s intentional, to show that a template is still just an HTML file first, before anything special gets added to it.<\/p>\n\n\n\n<h2 id=\"step-3-rendering-the-template-from-a-view\" class=\"wp-block-heading\">Step 3: Rendering the Template From a View<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Update your <code>home<\/code> view to use <code>render()<\/code> instead of building the HTML manually:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">python<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from django.shortcuts import render\n\ndef home(request):\n    return render(request, 'pages\/home.html')<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"928\" height=\"446\" src=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-25.png\" alt=\"Django Template Language Explained\" class=\"wp-image-1748\" srcset=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-25.png 928w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-25-300x144.png 300w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-25-768x369.png 768w\" sizes=\"(max-width: 928px) 100vw, 928px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"938\" height=\"569\" src=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-26.png\" alt=\"Django Template Language Explained\" class=\"wp-image-1749\" srcset=\"https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-26.png 938w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-26-300x182.png 300w, https:\/\/nayananimsara.online\/wp-content\/uploads\/2026\/09\/image-26-767x465.png 767w\" sizes=\"(max-width: 938px) 100vw, 938px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s the whole view now. <code>render()<\/code> takes the request, finds the template by its path, and returns it as an <code>HttpResponse<\/code> behind the scenes \u2014 you don&#8217;t have to build the response object by hand anymore. Refresh your browser, and the page should look identical to before, just coming from a file instead of a string.<\/p>\n\n\n\n<h2 id=\"step-4-displaying-a-variable-with-dtl\" class=\"wp-block-heading\">Step 4: Displaying a Variable With DTL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s where DTL syntax actually shows up, and where this lesson stays focused. Update the view to pass some data along with the template:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">python<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def home(request):\n    context = {\n        'site_name': 'My Django Site',\n    }\n    return render(request, 'pages\/home.html', context)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That dictionary is called the context. Now, inside <code>home.html<\/code>, reference it using double curly braces:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">html<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;h1&gt;Welcome to {{ site_name }}&lt;\/h1&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Reload the page, and instead of hardcoded text, you&#8217;ll see whatever value the view passed in. That double-brace syntax, <code>{{ variable_name }}<\/code>, is the core of DTL for this lesson \u2014 it&#8217;s how a template pulls in a Python value and displays it as text.<\/p>\n\n\n\n<h2 id=\"try-it-with-a-second-variable\" class=\"wp-block-heading\">Try It With a Second Variable<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Add one more value to the context to get comfortable with the pattern before moving on:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">python<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def home(request):\n    context = {\n        'site_name': 'My Django Site',\n        'tagline': 'Learning Django one lesson at a time.',\n    }\n    return render(request, 'pages\/home.html', context)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">html<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;h1&gt;Welcome to {{ site_name }}&lt;\/h1&gt;\n&lt;p&gt;{{ tagline }}&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nothing complicated here, just repetition of the same idea \u2014 a Python value goes into the context dictionary, and <code>{{ }}<\/code> pulls it into the HTML wherever it&#8217;s referenced.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[Screenshot spot: your rendered homepage showing both variables displaying correctly \u2014 worth noting what values you actually used.]<\/p>\n\n\n\n<h2 id=\"what-hasnt-been-covered-yet\" class=\"wp-block-heading\">What Hasn&#8217;t Been Covered Yet<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This post stops deliberately at variable display. Logic tags like <code>{% if %}<\/code> and <code>{% for %}<\/code>, along with template inheritance using <code>{% extends %}<\/code> and <code>{% block %}<\/code>, are both covered in separate lessons later in this series rather than rushed in here. Trying to absorb variables, conditionals, loops, and inheritance all in one sitting tends to blur together \u2014 keeping this one scoped to just <code>{{ }}<\/code> makes it easier to actually retain.<\/p>\n\n\n\n<h2 id=\"a-mistake-worth-flagging-early\" class=\"wp-block-heading\">A Mistake Worth Flagging Early<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If your template renders blank or throws a &#8220;TemplateDoesNotExist&#8221; error, the nested folder structure \u2014 <code>templates\/pages\/home.html<\/code>, not just <code>templates\/home.html<\/code> \u2014 is the first thing to check. It trips up almost everyone the first time, myself included.<\/p>\n\n\n\n<h2 id=\"series-connections\" class=\"wp-block-heading\">Series Connections<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This lesson replaces the <code>HttpResponse<\/code>-based approach used throughout the earlier posts in this series, including the dynamic single post page tutorial \u2014 worth revisiting to see exactly what problem templates are solving. For the complete reference on variables and context beyond what&#8217;s covered here, the <a href=\"https:\/\/docs.djangoproject.com\/en\/stable\/ref\/templates\/language\/\" target=\"_blank\" rel=\"noopener\">official Django documentation on the template language<\/a> is worth keeping open while practicing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Try converting your About page to use <code>render()<\/code> and a <code>{{ }}<\/code> variable on your own before the next lesson. That repetition is what makes this piece stick before tags and inheritance get introduced.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<div class=\"tg-oembed-container\"><iframe title=\"WebHD 720p 14\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/iVp6NOTtDVg?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/div>\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/nayananimsara.online\/course\/django-course-sinhala\/\" target=\"_blank\" data-type=\"link\" data-id=\"https:\/\/nayananimsara.online\/course\/django-course-sinhala\/\" rel=\"noreferrer noopener\">Our Full Course<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Django Template Language (DTL) Explained: Part 1 for Beginners Django Template Language Explained, Every view built so far in this course has had the same problem buried inside it. The homepage, the About page, the blog post view \u2014 each one carries a full copy of the same navbar, the same &lt;!DOCTYPE html&gt;, the same [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"elearning_container_layout":"tg-site-layout--default","elearning_sidebar_layout":"tg-site-layout--default","elearning_remove_content_margin":false,"elearning_sidebar":"default","elearning_transparent_header":"customizer","elearning_logo":0,"elearning_header_style":"default","elearning_menu_item_color":"","elearning_menu_item_hover_color":"","elearning_menu_item_active_color":"","elearning_menu_item_active_style":"","elearning_page_header":true,"footnotes":""},"categories":[64],"tags":[],"class_list":["post-1742","post","type-post","status-publish","format-standard","hentry","category-django"],"_links":{"self":[{"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/posts\/1742","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/comments?post=1742"}],"version-history":[{"count":3,"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/posts\/1742\/revisions"}],"predecessor-version":[{"id":1752,"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/posts\/1742\/revisions\/1752"}],"wp:attachment":[{"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/media?parent=1742"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/categories?post=1742"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nayananimsara.online\/wp-json\/wp\/v2\/tags?post=1742"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}