TemplateView in Django

In questo articolo vediamo in dettaglio come usare TemplateView per servire pagine basate su template in modo idiomatico, anche con supporto asincrono, extra contesto e personalizzazioni avanzate.

Cos’è TemplateView e quando usarla

TemplateView è una view generica che renderizza un template e, per convenzione, non effettua logica di dominio complessa. È perfetta per pagine “statiche” o quasi (home, about, landing, robots, policy) dove serve soltanto passare un contesto al template. Internamente eredita da TemplateResponseMixin e ContextMixin e restituisce una TemplateResponse, che differisce da una HttpResponse perché il rendering può essere differito per consentire l’intervento della template response middleware.

Esempio base via URLconf

Il modo più diretto per usarla è dichiararla direttamente nell’URLconf:

# urls.py
from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
  path(
  "",
  TemplateView.as_view(template_name="pages/home.html"),
  name="home",
),
] 

Questa view renderizza il template indicato. Eventuali parametri catturati dall’URL (per es. <slug:slug>) sono inclusi automaticamente nel contesto.

Passare dati al template

1) extra_context (per costanti)

# urls.py
path(
    "about/",
    TemplateView.as_view(
        template_name="pages/about.html",
        extra_context={"title": "Chi siamo", "show_cta": True},
    ),
    name="about",
)

extra_context è comodo per valori statici e può essere impostato anche come attributo di classe.

2) get_context_data() (per contenuto dinamico)

# views.py
from django.views.generic import TemplateView
from datetime import date

class HomeView(TemplateView):
template_name = "pages/home.html"

def get_context_data(self, **kwargs):
    ctx = super().get_context_data(**kwargs)
    ctx["today"] = date.today()
    ctx["user_agent"] = self.request.META.get("HTTP_USER_AGENT", "")
    return ctx

Questo metodo è fornito da ContextMixin ed è il punto giusto per arricchire il contesto con dati calcolati.

Supporto asincrono

In Django 5.2 le view possono essere dichiarate asincrone: per una class-based view si definiscono come async def i metodi HTTP (per esempio get()). Non si devono mescolare handler sincroni e asincroni nella stessa classe.

# views.py
from django.views.generic import TemplateView
import httpx

class WeatherView(TemplateView):
template_name = "pages/weather.html"

async def get(self, request, *args, **kwargs):
    # Esempio: chiamata IO-bound non bloccante
    async with httpx.AsyncClient() as client:
        r = await client.get("https://api.example.com/weather?city=Rome")
    # Iniettiamo il risultato nel contesto e renderizziamo
    context = self.get_context_data(forecast=r.json())
    return self.render_to_response(context)

Attributi e metodi utili

  • template_name: stringa o lista; può essere risolta anche via get_template_names().
  • extra_context: dizionario aggregato al contesto.
  • content_type: per impostare il tipo MIME (es. text/xml o application/json).
  • get_context_data(**kwargs): arricchisce il contesto.
  • render_to_response(context, **response_kwargs): restituisce una TemplateResponse (render differito).

Parametri URL nel contesto

I parametri catturati nell’URL sono inclusi automaticamente nel contesto; ad esempio <slug:page> diventa page nel template.

# urls.py
path(
    "docs/<slug:page>/",
    TemplateView.as_view(template_name="docs/page.html"),
    name="docs-page",
)
{# templates/docs/page.html #}
<h1>Pagina: {{ page|title }}</h1>

Comportamento documentato dalle class-based views di base.

Selezione dinamica del template

Puoi determinare il template a runtime sovrascrivendo get_template_names():

class MarketingPageView(TemplateView):
    def get_template_names(self):
        if self.request.GET.get("variant") == "b":
            return ["pages/landing_b.html"]
        return ["pages/landing_a.html"]

Utile per A/B test semplici senza introdurre condizionali nei template.

Impostare il content_type (XML/JSON/Plain)

TemplateView può servire contenuti non-HTML impostando content_type:

# urls.py — robots.txt
path(
    "robots.txt",
    TemplateView.as_view(
        template_name="misc/robots.txt",
        content_type="text/plain"
    ),
)
# templates/misc/robots.txt
User-agent: *
Disallow:
Sitemap: https://example.com/sitemap.xml

Il rendering differito di TemplateResponse consente a eventuali middleware di modificare template/contesto prima che la risposta venga materializzata.

Confronto rapido: TemplateView vs funzione render()

  • render() (FBV): semplice per singole view funzionali.
  • TemplateView (CBV): struttura riusabile (ereditarietà/mixin), override puntuali (get_context_data, get_template_names), integrazione con dispatch e metodi HTTP (anche async). In entrambi i casi alla fine si produce una TemplateResponse.

Best practice

  1. Tieni la logica business fuori da TemplateView: se la pagina richiede query/IO complessi, valuta una CBV dedicata o una service/facade, e limita TemplateView al rendering.
  2. Usa extra_context per costanti, get_context_data() per dinamica: separa le responsabilità.
  3. Attento al misto sync/async: in una stessa classe non definire handler sia sincroni sia asincroni.
  4. Sfrutta parametri URL nel contesto: riduci boilerplate quando i dati arrivano dalla route.
Torna su