Django Templates and Static Files
Django templates help you show dynamic data in HTML. This chapter explains templates, static files, app setup, and Tailwind in simple steps. By the end, you will know how to create reusable templates, serve static files, and use Tailwind for styling in your Django projects.
Django Template Language (DTL) vs Jinja2
Section titled “Django Template Language (DTL) vs Jinja2”Django ships with its own template engine called Django Template Language (DTL). DTL syntax is similar to Jinja2, so many examples look alike, but DTL is the default and recommended engine for standard Django projects.
Keep using DTL for most Django tutorials and simple sites. If you prefer Jinja2, Django supports it as an alternative backend.
Template settings
Section titled “Template settings”By default Django searches for templates in a templates/ folder inside each app (when APP_DIRS=True) and in directories you list under TEMPLATES[0]["DIRS"] in settings.py.
Add a project-level templates directory like this:
TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "templates"], # project-level templates "APP_DIRS": True, # include app-level templates "OPTIONS": { # context processors, etc. }, },]Basic template usage
Section titled “Basic template usage”Use double curly braces to output variables and {% %} for template tags.
Hello {{ name }}!If the view passes name = "Kumar Shail", the rendered output will be Hello Kumar Shail!.
Common template tags
Section titled “Common template tags”{% if name %} Hello, {{ name }}!{% endif %}{% for item in items %} {{ item }}{% endfor %}block / endblock: define overridable sections in a base template.
Section titled “block / endblock: define overridable sections in a base template.”<title>{% block title %}My Website{% endblock title %}</title>extends: inherit from a base template.
Section titled “extends: inherit from a base template.”{% extends "base.html" %}include: insert another template file (useful for headers/footers).
Section titled “include: insert another template file (useful for headers/footers).”{% include "partials/header.html" %}load static / static: use these to reference static assets (CSS, JS, images).
Section titled “load static / static: use these to reference static assets (CSS, JS, images).”{% load static %}<link rel="stylesheet" href="{% static 'css/style.css' %}">url: reverse URL names in templates.
Section titled “url: reverse URL names in templates.”<a href="{% url 'all_items' %}">All Items</a>Template inheritance
Section titled “Template inheritance”Template inheritance keeps common layout in one file and lets child templates override only the sections they need.
templates/base.html (example):
{% load static %}<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="{% static 'css/style.css' %}"> <title>{% block title %}My Project{% endblock title %}</title></head><body> <nav><!-- common navbar --></nav> <main>{% block content %}{% endblock content %}</main> <footer><!-- common footer --></footer> </body></html>Child template (core/templates/core/all_items.html):
{% extends "base.html" %}
{% block title %}All Items{% endblock title %}
{% block content %} <h1>All Items</h1> <p>Welcome {{ name }}</p> {% for item in names %} <p>{{ item }}</p> {% endfor %}{% endblock content %}Serving templates from views
Section titled “Serving templates from views”Render templates from a view using django.shortcuts.render.
core/views.py:
from django.shortcuts import render
def all_items(request): context = { "name": "Kumar Shail", "names": ["Tea", "Coffee", "Juice"], } return render(request, "core/all_items.html", context)core/urls.py:
from django.urls import pathfrom . import views
urlpatterns = [ path("", views.all_items, name="all_items"),]Include the app URLs in the project urls.py:
from django.contrib import adminfrom django.urls import include, path
urlpatterns = [ path("admin/", admin.site.urls), path("items/", include("core.urls")),]Visit http://localhost:8000/items/ to see the page.
Serving a template directly from a URL
Section titled “Serving a template directly from a URL”For static pages without dynamic context, use TemplateView.
app/urls.py:
from django.urls import pathfrom django.views.generic import TemplateView
urlpatterns = [ path("", TemplateView.as_view(template_name="core/index.html"), name="index"),]Static files
Section titled “Static files”Static files are files served directly to the client: CSS, JavaScript, images, fonts, etc. During development, runserver serves static files when DEBUG=True. In production, use a dedicated static file server or a middleware like WhiteNoise.
Install WhiteNoise (or use your package manager):
uv add whitenoiseAdd WhiteNoise to MIDDLEWARE in settings.py (after SecurityMiddleware):
MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", # other middleware...]
STATIC_URL = "/static/"STATICFILES_DIRS = [BASE_DIR / "static"]STATIC_ROOT = BASE_DIR / "staticfiles"STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"Create a sample stylesheet at core/static/core/css/style.css or static/css/style.css:
body { font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial; padding: 1rem;}Collect static files for production with manage.py collectstatic and serve STATIC_ROOT from your web server or use WhiteNoise.
Tailwind CSS integration
Section titled “Tailwind CSS integration”This project uses django-tailwind for a convenient Tailwind workflow inside Django. The commands below assume the helper uv is available in your environment; otherwise install packages with pip and run management commands with python manage.py.
Install the required packages:
uv add django-tailwind django-browser-reloadAdd the Tailwind and theme apps to INSTALLED_APPS in settings.py:
INSTALLED_APPS = [ # other apps... "tailwind", "theme", # the Tailwind theme app created by tailwind init]
# development-only toolsif ENVIRONMENT != PRODUCTION: INSTALLED_APPS += ["django_browser_reload"]
TAILWIND_APP_NAME = "theme"INTERNAL_IPS = ["127.0.0.1", "localhost"]NPM_BIN_PATH = "npm" if os.name != "nt" else r"C:\Program Files\nodejs\npm.cmd"Add django_browser_reload middleware in development:
if ENVIRONMENT != PRODUCTION: MIDDLEWARE += ["django_browser_reload.middleware.BrowserReloadMiddleware"]Add the reload URL when in development:
from django.conf import settingsfrom django.urls import include, path
urlpatterns = [ path("admin/", admin.site.urls), path("items/", include("core.urls")),]
if settings.ENVIRONMENT != settings.PRODUCTION: urlpatterns += [path("__reload__/,", include("django_browser_reload.urls"))]Initialize and install the Tailwind toolchain (run in your project root):
uv run python manage.py tailwind inituv run python manage.py tailwind installUse Tailwind in templates (example base.html):
{% load static %}{% load static tailwind_tags %}<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> {% tailwind_css %} <title>{% block title %}My Project{% endblock title %}</title></head><body class="bg-slate-100 text-slate-900"> {% block content %}{% endblock content %}</body></html>During development run two processes:
uv run python manage.py runserveruv run python manage.py tailwind startTo build Tailwind assets for production:
uv run python manage.py tailwind build