URL-distributör¶
Ett rent och elegant URL-schema är en viktig detalj i en högkvalitativ webbapplikation. Med Django kan du designa webbadresser hur du vill, utan några begränsningar av ramverket.
Se ”Cool URIs don’t change” av Tim Berners-Lee, skaparen av World Wide Web, för utmärkta argument för varför webbadresser ska vara rena och användbara.
Översikt¶
För att utforma webbadresser för en app skapar du en Python-modul som informellt kallas URLconf (URL-konfiguration). Den här modulen är ren Python-kod och är en mappning mellan URL-sökvägsuttryck till Python-funktioner (dina vyer).
Denna mappning kan vara så kort eller så lång som behövs. Den kan referera till andra mappningar. Och eftersom det är ren Python-kod kan den konstrueras dynamiskt.
Django tillhandahåller också ett sätt att översätta webbadresser enligt det aktiva språket. Se :ref:``internationaliseringsdokumentation <url-internationalization>` för mer information.
Hur Django behandlar en förfrågan¶
När en användare begär en sida från din Django-drivna webbplats är detta den algoritm som systemet följer för att avgöra vilken Python-kod som ska köras:
Django bestämmer vilken URLconf-modul som ska användas. Vanligtvis är detta värdet på
ROOT_URLCONF
-inställningen, men om det inkommandeHttpRequest
-objektet har etturlconf
-attribut (inställt av middleware), kommer dess värde att användas i stället förROOT_URLCONF
-inställningen.Django laddar den Python-modulen och letar efter variabeln
urlpatterns
. Detta bör vara en sequence avdjango.urls.path()
och/ellerdjango.urls.re_path()
instanser.Django går igenom varje URL-mönster, i ordning, och stannar vid det första som matchar den begärda URL:en och matchar mot
path_info
.När ett av URL-mönstren matchar importerar och anropar Django den angivna vyn, som är en Python-funktion (eller en klassbaserad vy). Vyn får följande argument:
En instans av
HttpRequest
.Om det matchade URL-mönstret inte innehåller några namngivna grupper anges matchningarna från det reguljära uttrycket som positionsargument.
Nyckelordsargumenten består av alla namngivna delar som matchas av sökvägsuttrycket som tillhandahålls, åsidosatta av alla argument som anges i det valfria
kwargs
-argumentet tilldjango.urls.path()
ellerdjango.urls.re_path()
.
Om inget URL-mönster matchar, eller om ett undantag uppstår under någon punkt i denna process, anropar Django en lämplig felhanteringsvy. Se Felhantering nedan.
Exempel¶
Här är ett exempel på URLconf:
from django.urls import path
from . import views
urlpatterns = [
path("articles/2003/", views.special_case_2003),
path("articles/<int:year>/", views.year_archive),
path("articles/<int:year>/<int:month>/", views.month_archive),
path("articles/<int:year>/<int:month>/<slug:slug>/", views.article_detail),
]
Anteckningar:
Använd vinkelparenteser för att fånga ett värde från URL:en.
Fångade värden kan eventuellt innehålla en konverteringstyp. Använd t.ex.
<int:name>
för att fånga en heltalsparameter. Om en omvandlare inte ingår matchas alla strängar, exklusive tecknet/
.Det finns inget behov av att lägga till ett inledande snedstreck, eftersom alla webbadresser har det. Till exempel är det
artiklar
, inte/artiklar
.
Exempel på förfrågningar:
En förfrågan till
/articles/2005/03/
skulle matcha den tredje posten i listan. Django skulle anropa funktionenviews.month_archive(request, year=2005, month=3)
./articles/2003/
skulle matcha det första mönstret i listan, inte det andra, eftersom mönstren testas i ordning och det första är det första testet som ska godkännas. Känn dig fri att utnyttja beställningen för att infoga specialfall som detta. Här skulle Django anropa funktionenviews.special_case_2003(request)
/articles/2003
skulle inte matcha något av dessa mönster, eftersom varje mönster kräver att URL:en slutar med ett snedstreck./articles/2003/03/building-a-django-site/
skulle matcha det slutliga mönstret. Django skulle anropa funktionenviews.article_detail(request, year=2003, month=3, slug="building-a-django-site")
.
Banomvandlare¶
Följande sökvägskonverterare är tillgängliga som standard:
str
- Matchar alla icke-tomma strängar, exklusive sökvägsseparatorn'/'`
. Detta är standardvärdet om en konverterare inte ingår i uttrycket.int
- Motsvarar noll eller ett positivt heltal. Returnerar ettint
.slug
- Matchar alla slug-strängar som består av ASCII-bokstäver eller siffror, plus bindestreck och understreck. Till exempelbygg-din-1:a-django-sida
.uuid
- Matchar ett formaterat UUID. För att förhindra att flera webbadresser mappas till samma sida måste bindestreck inkluderas och bokstäver måste vara gemener. Till exempel075194d3-6885-417e-a8a8-6c931e272f00
. Returnerar enUUID
-instans.path
- Matchar alla icke-tomma strängar, inklusive sökvägsseparatorn'/'`
. Detta gör att du kan matcha mot en komplett URL-sökväg snarare än ett segment av en URL-sökväg som medstr
.
Registrering av anpassade sökvägsomvandlare¶
För mer komplexa matchningskrav kan du definiera dina egna banomvandlare.
En converter är en klass som innehåller följande:
Ett
regex
-klassattribut, som en sträng.En
to_python(self, value)
-metod, som hanterar konvertering av den matchade strängen till den typ som ska skickas till vyfunktionen. Den bör ge upphov tillValueError
om den inte kan konvertera det givna värdet. EttValueError
tolkas som ingen matchning och som en konsekvens av detta skickas ett 404-svar till användaren om inte ett annat URL-mönster matchar.En
to_url(self, value)
-metod, som hanterar konvertering av Python-typen till en sträng som ska användas i URL:en. Den bör ge upphov tillValueError
om den inte kan konvertera det givna värdet. EttValueError
tolkas som ingen matchning och som en konsekvens av detta kommerreverse()
att geNoReverseMatch
om inte ett annat URL-mönster matchar.
Till exempel:
class FourDigitYearConverter:
regex = "[0-9]{4}"
def to_python(self, value):
return int(value)
def to_url(self, value):
return "%04d" % value
Registrera anpassade omvandlarklasser i din URLconf med register_converter()
:
from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FourDigitYearConverter, "yyyy")
urlpatterns = [
path("articles/2003/", views.special_case_2003),
path("articles/<yyyy:year>/", views.year_archive),
...,
]
Ersatt sedan version 5.1: Att åsidosätta befintliga omvandlare med django.urls.register_converter()
är föråldrat.
Använda reguljära uttryck¶
Om syntaxen för sökvägar och omvandlare inte är tillräcklig för att definiera dina URL-mönster kan du också använda reguljära uttryck. För att göra det, använd re_path()
istället för path()
.
I Python är syntaxen för namngivna grupper av reguljära uttryck (?P<name>pattern)
, där name
är namnet på gruppen och pattern
är ett mönster som ska matchas.
Här är exemplet URLconf från tidigare, omskrivet med hjälp av reguljära uttryck:
from django.urls import path, re_path
from . import views
urlpatterns = [
path("articles/2003/", views.special_case_2003),
re_path(r"^articles/(?P<year>[0-9]{4})/$", views.year_archive),
re_path(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive),
re_path(
r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$",
views.article_detail,
),
]
Detta åstadkommer ungefär samma sak som det föregående exemplet, förutom:
De exakta webbadresser som kommer att matcha är något mer begränsade. Till exempel kommer årtalet 10000 inte längre att matcha eftersom årtalen måste vara exakt fyra siffror långa.
Varje argument som fångas upp skickas till vyn som en sträng, oavsett vilken typ av matchning det reguljära uttrycket ger.
När du byter från att använda path()
till re_path()
eller vice versa är det särskilt viktigt att vara medveten om att typen av vyargument kan ändras och att du därför kan behöva anpassa dina vyer.
Använda icke namngivna grupper av reguljära uttryck¶
Förutom syntaxen för namngivna grupper, t.ex. (?P<year>[0-9]{4})
, kan du också använda den kortare syntaxen för icke namngivna grupper, t.ex. ([0-9]{4})
.
Denna användning är inte särskilt rekommenderad eftersom det gör det lättare att av misstag införa fel mellan den avsedda betydelsen av en match och argumenten i vyn.
I båda fallen rekommenderas att endast en stil används inom en given regex. När båda stilarna blandas ignoreras alla icke namngivna grupper och endast namngivna grupper skickas till view-funktionen.
Nästlade argument¶
Reguljära uttryck tillåter nästlade argument, och Django kommer att lösa dem och skicka dem till vyn. Vid reversering kommer Django att försöka fylla i alla yttre infångade argument och ignorera alla nästlade infångade argument. Tänk på följande URL-mönster som valfritt tar ett sidargument:
from django.urls import re_path
urlpatterns = [
re_path(r"^blog/(page-([0-9]+)/)?$", blog_articles), # bad
re_path(r"^comments/(?:page-(?P<page_number>[0-9]+)/)?$", comments), # good
]
Båda mönstren använder nästlade argument och kommer att lösas: till exempel kommer blog/page-2/
att resultera i en matchning till blog_articles
med två positionella argument: page-2/
och 2
. Det andra mönstret för comments
kommer att matcha comments/page-2/
med nyckelordsargumentet page_number
satt till 2. Det yttre argumentet i detta fall är ett icke-fångande argument (?:...)
.
Vyn blog_articles
behöver det yttersta infångade argumentet för att kunna vändas, page-2/
eller inga argument i det här fallet, medan comments
kan vändas med antingen inga argument eller ett värde för page_number
.
Kapslade argument skapar en stark koppling mellan vyargumenten och URL:en, vilket illustreras av blog_articles
: vyn tar emot en del av URL:en (page-2/
) i stället för bara det värde som vyn är intresserad av. Denna koppling är ännu mer uttalad vid reversering, eftersom vi för att reversera vyn måste skicka URL-biten istället för sidnumret.
En tumregel är att bara fånga de värden som vyn behöver arbeta med och att använda argument som inte fångas när det reguljära uttrycket behöver ett argument men vyn ignorerar det.
Vad URLconf söker efter¶
URLconf söker mot den begärda URL:en som en vanlig Python-sträng. Detta inkluderar inte GET- eller POST-parametrar eller domännamnet.
Till exempel, i en begäran till https://www.example.com/myapp/
kommer URLconf att leta efter myapp/
.
I en begäran till https://www.example.com/myapp/?page=3
kommer URLconf att leta efter myapp/
.
URLconf tittar inte på förfrågningsmetoden. Med andra ord kommer alla förfrågningsmetoder - POST
, GET
, HEAD
osv. – kommer att dirigeras till samma funktion för samma URL.
Ange standardvärden för vyargument¶
Ett praktiskt trick är att ange standardparametrar för dina vyers argument. Här är ett exempel på URLconf och view:
# URLconf
from django.urls import path
from . import views
urlpatterns = [
path("blog/", views.page),
path("blog/page<int:num>/", views.page),
]
# View (in blog/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...
I exemplet ovan pekar båda URL-mönstren på samma vy - views.page
- men det första mönstret fångar inte upp något från URL:en. Om det första mönstret matchar kommer funktionen page()
att använda sitt standardargument för num
, 1
. Om det andra mönstret matchar, kommer page()
att använda det värde för num
som fångades upp.
Prestanda¶
Django bearbetar reguljära uttryck i listan urlpatterns
som sammanställs första gången den öppnas. Efterföljande förfrågningar använder den cachade konfigurationen via URL-resolvern.
Syntax för variabeln ”Urlpatterns¶
urlpatterns
bör vara en sequence av path()
och/eller re_path()
instanser.
Felhantering¶
När Django inte kan hitta en matchning för den begärda URL:en, eller när ett undantag uppstår, anropar Django en vy för felhantering.
De vyer som ska användas i dessa fall specificeras av fyra variabler. Deras standardvärden bör räcka för de flesta projekt, men ytterligare anpassning är möjlig genom att åsidosätta deras standardvärden.
Se dokumentationen om :ref:``Anpassa felvyer <customizing-error-views>` för fullständig information.
Sådana värden kan ställas in i din rot-URLconf. Att ställa in dessa variabler i någon annan URLconf kommer inte att ha någon effekt.
Värdena måste vara callables, eller strängar som representerar den fullständiga Python-importvägen till den vy som ska anropas för att hantera det aktuella feltillståndet.
Variablerna är:
handler400
– Sedjango.conf.urls.handler400
.handler403
– Sedjango.conf.urls.handler403
.handler404
– Sedjango.conf.urls.handler404
.handler500
– Sedjango.conf.urls.handler500
.
Inkludera andra URLconfs¶
När som helst kan dina ”URL-mönster” ”inkludera” andra URLconf-moduler. Detta innebär i princip att en uppsättning webbadresser ”rotas” under andra.
Här är till exempel ett utdrag ur URLconf för själva Django-webbplatsen. Den innehåller ett antal andra URLconfs:
from django.urls import include, path
urlpatterns = [
# ... snip ...
path("community/", include("aggregator.urls")),
path("contact/", include("contact.urls")),
# ... snip ...
]
När Django stöter på include()
, hugger den bort den del av URL:en som matchade fram till den punkten och skickar den återstående strängen till den inkluderade URLconf för vidare bearbetning.
En annan möjlighet är att inkludera ytterligare URL-mönster genom att använda en lista med path()
-instanser. Tänk till exempel på denna URLconf:
from django.urls import include, path
from apps.main import views as main_views
from credit import views as credit_views
extra_patterns = [
path("reports/", credit_views.report),
path("reports/<int:id>/", credit_views.report),
path("charge/", credit_views.charge),
]
urlpatterns = [
path("", main_views.homepage),
path("help/", include("apps.help.urls")),
path("credit/", include(extra_patterns)),
]
I det här exemplet kommer webbadressen /credit/reports/
att hanteras av Django-vyn credit_views.report()
.
Detta kan användas för att ta bort redundans från URLconfs där ett enda mönsterprefix används upprepade gånger. Tänk till exempel på detta URLconf:
from django.urls import path
from . import views
urlpatterns = [
path("<page_slug>-<page_id>/history/", views.history),
path("<page_slug>-<page_id>/edit/", views.edit),
path("<page_slug>-<page_id>/discuss/", views.discuss),
path("<page_slug>-<page_id>/permissions/", views.permissions),
]
Vi kan förbättra detta genom att bara ange det gemensamma sökvägsprefixet en gång och gruppera de suffix som skiljer sig åt:
from django.urls import include, path
from . import views
urlpatterns = [
path(
"<page_slug>-<page_id>/",
include(
[
path("history/", views.history),
path("edit/", views.edit),
path("discuss/", views.discuss),
path("permissions/", views.permissions),
]
),
),
]
Uppfångade parametrar¶
En inkluderad URLconf tar emot eventuella parametrar från överordnade URLconfs, så följande exempel är giltigt:
# In settings/urls/main.py
from django.urls import include, path
urlpatterns = [
path("<username>/blog/", include("foo.urls.blog")),
]
# In foo/urls/blog.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.blog.index),
path("archive/", views.blog.archive),
]
I exemplet ovan skickas den fångade variabeln "username"
till den inkluderade URLconf, som förväntat.
Överföra extra alternativ till vyfunktioner¶
URLconfs har en krok som gör att du kan skicka extra argument till dina vyfunktioner, som en Python-ordbok.
Funktionen path()
kan ta ett valfritt tredje argument som bör vara en ordbok med extra nyckelordsargument som ska skickas till vyfunktionen.
Till exempel:
from django.urls import path
from . import views
urlpatterns = [
path("blog/<int:year>/", views.year_archive, {"foo": "bar"}),
]
I det här exemplet kommer Django att anropa views.year_archive(request, year=2005, foo='bar')
för en begäran till /blog/2005/
.
Denna teknik används i syndication framework för att skicka metadata och alternativ till vyer.
Hantering av konflikter
Det är möjligt att ha ett URL-mönster som fångar upp namngivna nyckelordsargument och även skickar argument med samma namn i sin ordbok med extra argument. När detta händer kommer argumenten i ordlistan att användas i stället för de argument som fångas upp i URL:en.
Skicka extra alternativ till include()
¶
På samma sätt kan du skicka extra alternativ till include()
och varje rad i den inkluderade URLconf kommer att skickas till de extra alternativen.
Till exempel är dessa två URLconf-uppsättningar funktionellt identiska:
Set ett:
# main.py
from django.urls import include, path
urlpatterns = [
path("blog/", include("inner"), {"blog_id": 3}),
]
# inner.py
from django.urls import path
from mysite import views
urlpatterns = [
path("archive/", views.archive),
path("about/", views.about),
]
Set två:
# main.py
from django.urls import include, path
from mysite import views
urlpatterns = [
path("blog/", include("inner")),
]
# inner.py
from django.urls import path
urlpatterns = [
path("archive/", views.archive, {"blog_id": 3}),
path("about/", views.about, {"blog_id": 3}),
]
Observera att extra alternativ alltid kommer att skickas till alla rader i den inkluderade URLconf, oavsett om radens vy faktiskt accepterar dessa alternativ som giltiga. Av denna anledning är denna teknik endast användbar om du är säker på att varje vy i den inkluderade URLconf accepterar de extra alternativ du skickar.
Omvänd upplösning av webbadresser¶
Ett vanligt behov när man arbetar med ett Django-projekt är möjligheten att få webbadresser i sina slutliga former antingen för inbäddning i genererat innehåll (vyer och tillgångars webbadresser, webbadresser som visas för användaren etc.) eller för hantering av navigeringsflödet på serversidan (omdirigeringar etc.)
Det är mycket önskvärt att undvika hårdkodning av dessa webbadresser (en mödosam, icke skalbar och felbenägen strategi). Lika farligt är det att utforma ad hoc-mekanismer för att generera webbadresser som är parallella med den design som beskrivs av URLconf, vilket kan leda till att webbadresser produceras som blir inaktuella med tiden.
Vad som behövs är med andra ord en DRY-mekanism. Bland andra fördelar skulle det göra det möjligt att utveckla URL-designen utan att behöva gå igenom hela projektets källkod för att söka efter och ersätta föråldrade URL:er.
Den primära information vi har tillgänglig för att få en URL är en identifiering (t.ex. namnet) av den vy som ansvarar för att hantera den. Andra delar av informationen som nödvändigtvis måste delta i sökningen efter rätt URL är typerna (positionella, nyckelord) och värdena för vyargumenten.
Django tillhandahåller en lösning så att URL-mapparen är den enda förvararen av URL-designen. Du matar den med din URLconf och sedan kan den användas i båda riktningarna:
Med utgångspunkt i en URL som begärs av användaren/webbläsaren anropar den rätt Django-vy och ger alla argument som den kan behöva med deras värden som extraheras från URL.
Med utgångspunkt från identifieringen av motsvarande Django-vy plus värdena för de argument som skulle skickas till den, får du den tillhörande URL:en.
Den första är den användning som vi har diskuterat i de tidigare avsnitten. Den andra är vad som kallas omvänd upplösning av webbadresser, omvänd URL-matchning, omvänd URL-uppslagning eller helt enkelt URL-reversering.
Django tillhandahåller verktyg för att utföra URL-reversering som matchar de olika lager där webbadresser behövs:
I mallar: Använda malltaggen
url
.I Python-kod: Med hjälp av funktionen
reverse()
.I kod på högre nivå relaterad till hantering av webbadresser för Django-modellinstanser: Metoden
get_absolute_url()
.
Exempel¶
Tänk igen på denna URLconf-post:
from django.urls import path
from . import views
urlpatterns = [
# ...
path("articles/<int:year>/", views.year_archive, name="news-year-archive"),
# ...
]
Enligt denna design är URL:en för arkivet som motsvarar år nnnn /artiklar/<nnnn>/
.
Du kan få dessa i mallkod genom att använda:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
Eller i Python-kod:
from django.http import HttpResponseRedirect
from django.urls import reverse
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse("news-year-archive", args=(year,)))
Om det av någon anledning skulle beslutas att URL:erna där innehållet i de årliga artikelarkiven publiceras ska ändras, behöver du bara ändra posten i URLconf.
I vissa scenarier där vyerna är av generisk karaktär kan det finnas ett många-till-ett-förhållande mellan webbadresser och vyer. I dessa fall är vynamnet inte en tillräckligt bra identifierare för det när det är dags att vända webbadresser. Läs nästa avsnitt för att få veta mer om den lösning som Django tillhandahåller för detta.
Namngivning av URL-mönster¶
För att kunna utföra URL-reversering måste du använda namngivna URL-mönster som i exemplen ovan. Strängen som används för URL-namnet kan innehålla vilka tecken du vill. Du är inte begränsad till giltiga Python-namn.
När du namnger URL-mönster, välj namn som sannolikt inte kommer att kollidera med andra applikationers val av namn. Om du kallar ditt URL-mönster comment
och ett annat program gör samma sak, beror den URL som reverse()
hittar på vilket mönster som är sist i ditt projekts urlpatterns
-lista.
Om du sätter ett prefix på dina URL-namn, kanske härlett från applikationens namn (t.ex. myapp-comment
i stället för comment
), minskar risken för kollisioner.
Du kan medvetet välja samma URL-namn som en annan applikation om du vill åsidosätta en vy. Till exempel är ett vanligt användningsfall att åsidosätta LoginView
. Delar av Django och de flesta tredjepartsappar antar att den här vyn har ett URL-mönster med namnet login
. Om du har en anpassad inloggningsvy och ger dess URL namnet login
, kommer reverse()`()
att hitta din anpassade vy så länge den finns i urlpatterns
efter att django.contrib.auth.urls
har inkluderats (om den inkluderas alls).
Du kan också använda samma namn för flera URL-mönster om de skiljer sig åt i sina argument. Förutom URL-namnet matchar reverse()
antalet argument och namnen på nyckelordsargumenten. Sökvägskonverterare kan också ge upphov till ValueError
för att indikera ingen matchning, se Registrering av anpassade sökvägsomvandlare för detaljer.
Namnrymder för URL¶
Introduktion¶
Med URL-namnrymder kan du unikt vända namngivna URL-mönster även om olika program använder samma URL-namn. Det är en god praxis för tredjepartsappar att alltid använda namnrymder för webbadresser (som vi gjorde i handledningen). På samma sätt kan du också vända webbadresser om flera instanser av en applikation distribueras. Med andra ord, eftersom flera instanser av en enda applikation kommer att dela namngivna webbadresser, ger namnrymder ett sätt att skilja dessa namngivna webbadresser åt.
Django-applikationer som använder URL-namnavstånd på rätt sätt kan distribueras mer än en gång för en viss webbplats. Till exempel har django.contrib.admin
en AdminSite
-klass som gör att du kan distribuera mer än en instans av admin. I ett senare exempel kommer vi att diskutera idén om att distribuera polls-programmet från handledningen på två olika platser så att vi kan erbjuda samma funktionalitet till två olika målgrupper (författare och utgivare).
En URL-namnrymd består av två delar, som båda är strängar:
- applikationens namnområde¶
Detta beskriver namnet på den applikation som distribueras. Varje instans av en enskild applikation kommer att ha samma applikationsnamnrymd. Till exempel har Djangos admin-applikation det något förutsägbara applikationsnamnområdet
'admin'
.- namnrymd för instans¶
Detta identifierar en specifik instans av en applikation. Instansnamnrymder bör vara unika för hela projektet. En instansnamnrymd kan dock vara densamma som applikationens namnrymd. Detta används för att ange en standardinstans av en applikation. Till exempel har standardinstansen Django admin ett instansnamnområde på
'admin'
.
Namngivna URL:er anges med operatorn ':'
. Huvudindexsidan för admin-programmet refereras till exempel med 'admin:index'
. Detta anger namnrymden 'admin'
och den namngivna URL:en 'index'
.
Namnrymder kan också vara nästlade. Den namngivna URL:en 'sports:polls:index'
letar efter ett mönster med namnet 'index'
i namnrymden 'polls'
som i sin tur definieras i namnrymden 'sports'
på högsta nivån.
Återställning av namnlösa URL:er¶
När Django får en URL med namnområde (t.ex. 'polls:index'
) att lösa, delar Django upp det fullständigt kvalificerade namnet i delar och försöker sedan följande uppslagning:
Först letar Django efter en matchande applikationsnamnrymd (i det här exemplet
'polls'
). Detta kommer att ge en lista över instanser av den applikationen.Om det finns en aktuell applikation definierad, hittar och returnerar Django URL-resolvern för den instansen. Den aktuella applikationen kan anges med argumentet
current_app
till funktionenreverse()
.Malltaggen
url
använder namnrymden för den aktuella vyn som aktuell applikation i enRequestContext
. Du kan åsidosätta denna standard genom att ställa in den aktuella applikationen på attributetrequest.current_app
.Om det inte finns någon aktuell applikation letar Django efter en standardapplikationsinstans. Standardapplikationsinstansen är den instans som har en instance namespace som matchar application namespace (i det här exemplet en instans av
polls
som heter'polls'
).Om det inte finns någon standardapplikationsinstans kommer Django att välja den senast distribuerade instansen av applikationen, oavsett vad dess instansnamn kan vara.
Om den angivna namnrymden inte matchar en applikationsnamnrymd i steg 1, kommer Django att försöka göra en direktuppslagning av namnrymden som en instansnamnrymd.
Om det finns nästlade namnrymder upprepas dessa steg för varje del av namnrymden tills endast vynamnet är olöst. Vynamnet kommer då att lösas upp till en URL i den namnrymd som har hittats.
Exempel¶
För att visa hur den här lösningsstrategin fungerar kan vi ta ett exempel med två instanser av applikationen polls
från handledningen: en som heter 'author-polls
och en som heter 'publisher-polls
. Antag att vi har förbättrat applikationen så att den tar hänsyn till instansnamnrymden när den skapar och visar omröstningar.
urls.py
¶from django.urls import include, path
urlpatterns = [
path("author-polls/", include("polls.urls", namespace="author-polls")),
path("publisher-polls/", include("polls.urls", namespace="publisher-polls")),
]
polls/urls.py
¶from django.urls import path
from . import views
app_name = "polls"
urlpatterns = [
path("", views.IndexView.as_view(), name="index"),
path("<int:pk>/", views.DetailView.as_view(), name="detail"),
...,
]
Med hjälp av denna inställning kan följande sökningar göras:
Om en av instanserna är aktuell - säg, om vi renderade detaljsidan i instansen
'author-polls
- kommer'polls:index
att lösa till indexsidan i instansen'author-polls
; dvs. båda följande kommer att resultera i"/author-polls/"
.I metoden för en klassbaserad syn:
reverse("polls:index", current_app=self.request.resolver_match.namespace)
och i mallen:
{% url 'polls:index' %}
Om det inte finns någon aktuell instans - till exempel om vi renderar en sida någon annanstans på webbplatsen - kommer
'polls:index'
att lösas till den senast registrerade instansen avpolls
. Eftersom det inte finns någon standardinstans (instansnamnrymden för'polls
), kommer den senast registrerade instansen avpolls
att användas. Detta skulle vara'publisher-polls
eftersom den deklareras sist iurlpatterns
.'author-polls:index'
kommer alltid att leda till indexsidan för instansen'author-polls'
(och på samma sätt för'publisher-polls'
) .
Om det också fanns en standardinstans - dvs. en instans med namnet 'polls'
- skulle den enda förändringen jämfört med ovan vara i det fall då det inte finns någon aktuell instans (den andra punkten i listan ovan). I det här fallet skulle 'polls:index'
resolva till indexsidan för standardinstansen istället för den instans som deklarerades sist i urlpatterns
.
URL-namnrymder och inkluderade URL-konf¶
Applikationsnamnrymder för inkluderade URLconfs kan anges på två sätt.
För det första kan du ange ett app_name
-attribut i den inkluderade URLconf-modulen, på samma nivå som urlpatterns
-attributet. Du måste skicka den faktiska modulen, eller en strängreferens till modulen, till include()
, inte själva listan med urlpatterns
.
polls/urls.py
¶from django.urls import path
from . import views
app_name = "polls"
urlpatterns = [
path("", views.IndexView.as_view(), name="index"),
path("<int:pk>/", views.DetailView.as_view(), name="detail"),
...,
]
urls.py
¶from django.urls import include, path
urlpatterns = [
path("polls/", include("polls.urls")),
]
De webbadresser som definieras i polls.urls
kommer att ha en applikationsnamnrymd polls
.
För det andra kan du inkludera ett objekt som innehåller inbäddade namnrymdsdata. Om du include()
en lista med path()
eller re_path()
instanser, kommer URL:erna som finns i det objektet att läggas till i det globala namnområdet. Men du kan också include()
en 2-tupel som innehåller:
(<list of path()/re_path() instances>, <application namespace>)
Till exempel:
from django.urls import include, path
from . import views
polls_patterns = (
[
path("", views.IndexView.as_view(), name="index"),
path("<int:pk>/", views.DetailView.as_view(), name="detail"),
],
"polls",
)
urlpatterns = [
path("polls/", include(polls_patterns)),
]
Detta kommer att inkludera de nominerade URL-mönstren i den angivna applikationens namnrymd.
Instansens namnområde kan anges med argumentet namespace
till include()
. Om instansnamnområdet inte anges kommer det att vara standard för det inkluderade URLconfs applikationsnamnområde. Detta innebär att det också kommer att vara standardinstansen för det namnområdet.