Mallar¶
Eftersom Django är ett webbramverk behöver det ett bekvämt sätt att generera HTML dynamiskt. Det vanligaste tillvägagångssättet bygger på mallar. En mall innehåller de statiska delarna av den önskade HTML-utskriften samt en speciell syntax som beskriver hur dynamiskt innehåll ska infogas. För ett praktiskt exempel på hur man skapar HTML-sidor med mallar, se Tutorial 3.
Ett Django-projekt kan konfigureras med en eller flera mallmotorer (eller till och med noll om du inte använder mallar). Django levererar inbyggda backends för sitt eget mallsystem, kreativt kallat Django template language (DTL), och för det populära alternativet Jinja2. Backends för andra mallspråk kan vara tillgängliga från tredje part. Du kan också skriva din egen anpassade backend, se Custom template backend
Django definierar ett standard-API för laddning och rendering av mallar oavsett backend. Laddning består av att hitta mallen för en given identifierare och förbehandla den, vanligtvis kompilera den till en representation i minnet. Rendering innebär att mallen interpoleras med kontextdata och att den resulterande strängen returneras.
Django mallspråk är Djangos eget mallsystem. Fram till Django 1.8 var det det enda inbyggda alternativet som fanns tillgängligt. Det är ett bra mallbibliotek även om det är ganska egensinnigt och har några idiosynkrasier. Om du inte har en tvingande anledning att välja en annan backend bör du använda DTL, särskilt om du skriver en pluggbar applikation och du tänker distribuera mallar. Djangos contrib-appar som innehåller mallar, som django.contrib.admin, använder DTL.
Av historiska skäl finns både det generiska stödet för mallmotorer och implementeringen av Djangos mallspråk i namnrymden django.template
.
Varning
Mallsystemet är inte säkert mot otillförlitliga mallförfattare. En webbplats bör till exempel inte tillåta sina användare att skapa egna mallar, eftersom mallförfattare kan utföra saker som XSS-attacker och komma åt egenskaper hos mallvariabler som kan innehålla känslig information.
Djangos mallspråk¶
Syntax¶
Om detta avsnitt
Detta är en översikt över Djangos mallspråks syntax. För detaljer se språksyntaxreferens.
En Django-mall är ett textdokument eller en Python-sträng som märks upp med hjälp av Djangos mallspråk. Vissa konstruktioner känns igen och tolkas av mallmotorn. De viktigaste av dessa är variabler och taggar.
En mall renderas med en kontext. Renderingen ersätter variabler med deras värden, som söks upp i kontexten, och kör taggar. Allt annat skrivs ut som det är.
Syntaxen i Djangos mallspråk består av fyra konstruktioner.
Variabler¶
En variabel matar ut ett värde från kontexten, som är ett diktatliknande objekt som mappar nycklar till värden.
Variabler omges av {{
och }}
så här:
My first name is {{ first_name }}. My last name is {{ last_name }}.
Med en kontext av {'first_name': 'John', 'last_name': 'Doe'}
, renderar denna mall till:
My first name is John. My last name is Doe.
Dictionary lookup, attribute lookup och list-index lookup implementeras med en punktnotation:
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}
Om en variabel motsvarar en anropsbar variabel kommer mallsystemet att anropa den utan argument och använda resultatet istället för den anropsbara variabeln.
Filter¶
Filter omvandlar värdena för variabler och taggargument.
De ser ut så här:
{{ django|title }}
Med en kontext av {'django': 'webbramverket för perfektionister med deadlines'}
, renderar denna mall till:
The Web Framework For Perfectionists With Deadlines
Vissa filter tar ett argument:
{{ my_date|date:"Y-m-d" }}
En referens av inbyggda filter finns tillgänglig liksom instruktioner för att skriva egna filter.
Kommentarer¶
Kommentarer ser ut så här:
{# this won't be rendered #}
En {% comment %}
-tagg ger kommentarer på flera rader.
Komponenter¶
Om detta avsnitt
Detta är en översikt över Django mallspråkets API:er. För detaljer se API-referens.
Motor¶
django.template.Engine
kapslar in en instans av Djangos mallsystem. Huvudskälet till att instansiera en Engine
direkt är att använda Djangos mallspråk utanför ett Django-projekt.
django.template.backends.django.DjangoTemplates
är ett tunt omslag som anpassar django.template.Engine
till Djangos API för mallbackends.
Mall¶
django.template.Template
representerar en kompilerad mall. Mallar erhålls med Engine.get_template()
eller Engine.from_string()
.
På samma sätt är django.template.backends.django.Template
en tunn omslag som anpassar django.template.Template
till det vanliga mall-API:et.
Kontext¶
django.template.Context
innehåller vissa metadata utöver kontextdata. Den skickas till Template.render()
för rendering av en mall.
django.template.RequestContext
är en underklass till Context
som lagrar den aktuella HttpRequest
och kör mallkontextprocessorer.
Det vanliga API:et har inte något motsvarande koncept. Kontextdata skickas i en vanlig dict
och den aktuella HttpRequest
skickas separat om det behövs.
Lastare¶
Template loaders är ansvariga för att hitta mallar, ladda dem och returnera Template
-objekt.
Django tillhandahåller flera inbyggda mallladdare och stöder skräddarsydda mallladdare.
Processorer i sammanhanget¶
Kontextprocessorer är funktioner som tar emot den aktuella HttpRequest
som ett argument och returnerar en dict
med data som ska läggas till i renderingskontexten.
Deras främsta användningsområde är att lägga till gemensamma data som delas av alla mallar i kontexten utan att upprepa kod i varje vy.
Django tillhandahåller många inbyggda kontextprocessorer, och du kan också implementera dina egna ytterligare kontextprocessorer.
Stöd för mallmotorer¶
Konfiguration¶
Mallmotorer konfigureras med inställningen TEMPLATES
. Det är en lista med konfigurationer, en för varje motor. Standardvärdet är tomt. I settings.py
som genereras av kommandot startproject
definieras ett mer användbart värde:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
# ... some options here ...
},
},
]
BACKEND
är en prickad Python-sökväg till en mallmotorklass som implementerar Djangos mallbackend API. De inbyggda backends är django.template.backends.django.DjangoTemplates
och django.template.backends.jinja2.Jinja2
.
Eftersom de flesta motorer laddar mallar från filer innehåller toppnivåkonfigurationen för varje motor två gemensamma inställningar:
DIRS
definierar en lista över kataloger där sökmotorn ska leta efter mallkällfiler, i sökordning.APP_DIRS
anger om motorn ska leta efter mallar i installerade program. Varje backend definierar ett konventionellt namn för den underkatalog i programmen där dess mallar ska lagras.
Även om det är ovanligt är det möjligt att konfigurera flera instanser av samma backend med olika alternativ. I så fall bör du definiera en unik NAME
för varje motor.
OPTIONS
innehåller backend-specifika inställningar.
Användning¶
Modulen django.template.loader
definierar två funktioner för att ladda mallar.
- get_template(template_name, using=None)[source]¶
Denna funktion laddar mallen med det angivna namnet och returnerar ett
Template
-objekt.Den exakta typen av returvärde beror på vilken backend som laddade mallen. Varje backend har sin egen
Template
-klass.get_template()
försöker varje mallmotor i ordning tills en lyckas. Om mallen inte kan hittas, ger detTemplateDoesNotExist
. Om mallen hittas men innehåller ogiltig syntax, ger den upphov tillTemplateSyntaxError
.Hur mallar söks och laddas beror på varje motors backend och konfiguration.
Om du vill begränsa sökningen till en viss mallmotor ska du ange motorns
NAME
i argumentetusing
.
- select_template(template_name_list, using=None)[source]¶
select_template()
är precis somget_template()
, förutom att den tar en lista med mallnamn. Den prövar varje namn i ordning och returnerar den första mallen som finns.
Om inläsningen av en mall misslyckas kan följande två undantag, definierade i django.template
, uppstå:
- exception TemplateDoesNotExist(msg, tried=None, backend=None, chain=None)[source]¶
Detta undantag uppstår när en mall inte kan hittas. Det accepterar följande valfria argument för att fylla i :ref:
mall postmortem <template-postmortem>
på felsökningssidan:backend
Den backend-instans för mallen som undantaget härrörde från.
försökte
En lista över källor som provades när mallen hittades. Detta är formaterat som en lista med tupler som innehåller
(ursprung, status)
, därursprung
är ett :ref:ursprungsliknande <template-origin-api>`-objekt och ``status
är en sträng med anledningen till att mallen inte hittades.kedja
En lista över mellanliggande
TemplateDoesNotExist
-undantag som uppstår när man försöker ladda en mall. Detta används av funktioner, såsomget_template()
, som försöker ladda en viss mall från flera motorer.
- exception TemplateSyntaxError(msg)[source]¶
Detta undantag uppstår när en mall har hittats men innehåller fel.
Template
-objekt som returneras av get_template()
och select_template()
måste tillhandahålla en render()
-metod med följande signatur:
- Template.render(context=None, request=None)¶
Renderar denna mall med ett givet sammanhang.
Om
context
anges måste det vara endict
. Om det inte anges kommer mallen att renderas med en tom kontext.Om
request
anges måste det vara enHttpRequest
. Sedan måste motorn göra den, liksom CSRF-token, tillgänglig i mallen. Hur detta uppnås är upp till varje backend.
Här är ett exempel på sökalgoritmen. I det här exemplet är TEMPLATES
inställningen:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
"/home/html/example.com",
"/home/html/default",
],
},
{
"BACKEND": "django.template.backends.jinja2.Jinja2",
"DIRS": [
"/home/html/jinja2",
],
},
]
Om du anropar get_template('story_detail.html')
, här är filerna som Django kommer att leta efter, i ordning:
/home/html/example.com/story_detail.html
('django'
motor)/home/html/default/story_detail.html
('django'
motor)/home/html/jinja2/story_detail.html
('jinja2'
motor)
Om du kallar select_template(['story_253_detail.html', 'story_detail.html'])
, här är vad Django kommer att leta efter:
/home/html/example.com/story_253_detail.html
('django'
motor)/home/html/default/story_253_detail.html
('django'
motor)/home/html/jinja2/story_253_detail.html
('jinja2'
motor)/home/html/example.com/story_detail.html
('django'
motor)/home/html/default/story_detail.html
('django'
motor)/home/html/jinja2/story_detail.html
('jinja2'
motor)
När Django hittar en mall som redan finns, slutar den att leta.
Använd django.template.loader.select_template()
för mer flexibilitet
Du kan använda select_template()
för flexibel mallinläsning. Om du till exempel har skrivit en nyhet och vill att vissa berättelser ska ha anpassade mallar, använd något som select_template(['story_%s_detail.html' % story.id, 'story_detail.html'])
. På så sätt kan du använda en anpassad mall för en enskild berättelse, med en reservmall för berättelser som inte har anpassade mallar.
Det är möjligt - och att föredra - att organisera mallar i underkataloger inuti varje katalog som innehåller mallar. Konventionen är att skapa en underkatalog för varje Django-app, med underkataloger inom dessa underkataloger efter behov.
Gör detta för din egen skull. Att lagra alla mallar på rotnivån i en enda katalog blir rörigt.
Om du vill ladda en mall som finns i en underkatalog använder du ett snedstreck, så här:
get_template("news/story_detail.html")
Med samma TEMPLATES
-alternativ som ovan, kommer detta att försöka ladda följande mallar:
/home/html/example.com/news/story_detail.html
('django'
motor)/home/html/default/news/story_detail.html
('django'
motor)/home/html/jinja2/news/story_detail.html
('jinja2'
motor)
För att minska den repetitiva karaktären av laddning och rendering av mallar tillhandahåller Django dessutom en genvägsfunktion som automatiserar processen.
- render_to_string(template_name, context=None, request=None, using=None)[source]¶
render_to_string()
laddar en mall somget_template()
och anropar dessrender()
-metod omedelbart. Den tar följande argument.template_name
Namnet på den mall som ska laddas och renderas. Om det är en lista med mallnamn använder Django
select_template()
istället förget_template()
för att hitta mallen.kontext
En
dict
som ska användas som mallens kontext för rendering.begäran
En valfri
HttpRequest
som kommer att vara tillgänglig under mallens renderingsprocess.använder
En valfri mallmotor
NAME
. Sökningen efter mallen kommer att begränsas till denna motor.
Exempel på användning:
from django.template.loader import render_to_string rendered = render_to_string("my_template.html", {"foo": "bar"})
Se även genvägen render()
som anropar render_to_string()
och matar in resultatet i en HttpResponse
som är lämplig att returnera från en vy.
Slutligen kan du använda konfigurerade motorer direkt:
Inbyggda backends¶
Ställ in BACKEND
till 'django.template.backends.django.DjangoTemplates'
för att konfigurera en Django-mallmotor.
När APP_DIRS
är True
, letar DjangoTemplates
motorer efter mallar i templates
underkatalogen för installerade applikationer. Detta generiska namn behölls för bakåtkompatibilitet.
DjangoTemplates
motorer accepterar följande :inställning:`OPTIONS <TEMPLATES-OPTIONS>`:
'autoescape'
: ett boolean som kontrollerar om HTML autoescaping är aktiverat.Standardvärdet är
True
.Varning
Sätt den bara till
False
om du renderar icke-HTML-mallar!'context_processors'
: en lista med prickade Python-sökvägar till anropsbara filer som används för att fylla i kontexten när en mall renderas med en begäran. Dessa callables tar ett request-objekt som sitt argument och returnerar endict
av objekt som ska sammanfogas i kontexten.Standardvärdet är en tom lista.
Se
RequestContext
för mer information.'debug'
: ett boolean som aktiverar/avaktiverar mallens felsökningsläge. Om det ärTrue
kommer den snygga felsidan att visa en detaljerad rapport för alla undantag som uppstår under mallrenderingen. Denna rapport innehåller det relevanta utdraget av mallen med lämplig rad markerad.Standardvärdet är värdet för inställningen
DEBUG
.'loaders'
: en lista med prickade Python-sökvägar till klasser för mallinläsare. VarjeLoader
-klass vet hur man importerar mallar från en viss källa. Alternativt kan en tupel användas istället för en sträng. Det första objektet i tupeln bör varaLoader
-klassens namn, och efterföljande objekt skickas tillLoader
under initialiseringen.Standardvärdet beror på värdena i
DIRS
ochAPP_DIRS
.Se Typer av lastare för mer information.
'string_if_invalid'
: utdata, i form av en sträng, som mallsystemet ska använda för ogiltiga (t.ex. felstavade) variabler.Standardvärdet är en tom sträng.
Se Hur ogiltiga variabler hanteras för mer information.
'file_charset'
: det teckensnitt som används för att läsa mallfiler på disken.Standardvärdet är
'utf-8'
.'bibliotek'
: En ordbok med etiketter och prickade Python-sökvägar för malltaggmoduler som ska registreras med mallmotorn. Detta kan användas för att lägga till nya bibliotek eller tillhandahålla alternativa etiketter för befintliga bibliotek. Till exempel:OPTIONS = { "libraries": { "myapp_tags": "path.to.myapp.tags", "admin.urls": "django.contrib.admin.templatetags.admin_urls", }, }
Bibliotek kan laddas genom att skicka motsvarande ordboksnyckel till taggen
{% load %}
.'builtins'
: En lista med prickade Python-sökvägar för malltaggmoduler som ska läggas till i built-ins. Till exempel:OPTIONS = { "builtins": ["myapp.builtins"], }
Taggar och filter från inbyggda bibliotek kan användas utan att först anropa
{% load %}
tagg.
Kräver att Jinja2 är installerat:
$ python -m pip install Jinja2
...\> py -m pip install Jinja2
Sätt BACKEND
till 'django.template.backends.jinja2.Jinja2'
för att konfigurera en Jinja2-motor.
När APP_DIRS
är True
letar Jinja2
-motorerna efter mallar i underkatalogen jinja2
för installerade program.
Den viktigaste posten i OPTIONS
är 'environment'
. Det är en prickad Python-sökväg till en anropsbar som returnerar en Jinja2-miljö. Standardvärdet är 'jinja2.Environment'
. Django anropar den anropsbara och skickar andra alternativ som nyckelordsargument. Dessutom lägger Django till standardvärden som skiljer sig från Jinja2:s för några alternativ:
'autoescape'
:True
'auto_reload'
:settings.DEBUG
'undefined'`
:DebugUndefined if settings.DEBUG else Undefined
Jinja2
motorer accepterar också följande :inställning:`OPTIONS <TEMPLATES-OPTIONS>`:
'context_processors'
: en lista med prickade Python-sökvägar till anropsbara filer som används för att fylla i kontexten när en mall renderas med en begäran. Dessa callables tar ett request-objekt som sitt argument och returnerar endict
av objekt som ska sammanfogas i kontexten.Standardvärdet är en tom lista.
Det är inte lämpligt att använda kontextprocessorer med Jinja2-mallar.
Kontextprocessorer är användbara med Django-mallar eftersom Django-mallar inte stöder anrop av funktioner med argument. Eftersom Jinja2 inte har den begränsningen rekommenderas det att du placerar den funktion som du vill använda som en kontextprocessor i de globala variabler som är tillgängliga för mallen med hjälp av
jinja2.Environment
enligt beskrivningen nedan. Du kan sedan anropa den funktionen i mallen:{{ function(request) }}
Vissa Django-mallars kontextprocessorer returnerar ett fast värde. För Jinja2-mallar är detta lager av indirektion inte nödvändigt eftersom du kan lägga till konstanter direkt i
jinja2.Environment
.Det ursprungliga användningsfallet för att lägga till kontextprocessorer för Jinja2 innebar:
Utföra en dyr beräkning som beror på begäran.
Behöver resultatet i varje mall.
Använda resultatet flera gånger i varje mall.
Om inte alla dessa villkor är uppfyllda är det mer i linje med designen av Jinja2 att skicka en funktion till mallen.
Standardkonfigurationen hålls avsiktligt till ett minimum. Om en mall renderas med en begäran (t.ex. när du använder render()
), lägger Jinja2
-backend till globalerna request
, csrf_input
och csrf_token
till kontexten. Bortsett från det skapar denna backend inte en Django-flavored miljö. Den känner inte till Django-filter och taggar. För att kunna använda Django-specifika API:er måste du konfigurera dem i miljön.
Du kan till exempel skapa myproject/jinja2.py
med följande innehåll:
from django.templatetags.static import static
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update(
{
"static": static,
"url": reverse,
}
)
return env
och ställa in alternativet 'environment'
till 'myproject.jinja2.environment'
.
Då kan du använda följande konstruktioner i Jinja2-mallar:
<img src="{{ static('path/to/company-logo.png') }}" alt="Company Logo">
<a href="{{ url('admin:index') }}">Administration</a>
Begreppen taggar och filter finns både i Djangos mallspråk och i Jinja2, men de används på olika sätt. Eftersom Jinja2 stöder att skicka argument till anropsbara funktioner i mallar, kan många funktioner som kräver en malltagg eller ett filter i Django-mallar uppnås genom att anropa en funktion i Jinja2-mallar, som visas i exemplet ovan. Jinja2:s globala namnrymd tar bort behovet av mallkontextprocessorer. Djangos mallspråk har inte någon motsvarighet till Jinja2-tester.