Skriva synpunkter¶
En view-funktion, eller kort och gott view, är en Python-funktion som tar emot en webbförfrågan och returnerar ett webbsvar. Detta svar kan vara HTML-innehållet på en webbsida, eller en omdirigering, eller ett 404-fel, eller ett XML-dokument, eller en bild … eller vad som helst, egentligen. Själva vyn innehåller den godtyckliga logik som krävs för att returnera svaret. Denna kod kan leva var du vill, så länge den finns på din Python-sökväg. Det finns inga andra krav - ingen ”magi”, så att säga. För att lägga koden någonstans är konventionen att lägga vyer i en fil som heter views.py
, placerad i din projekt- eller applikationskatalog.
En enkel vy¶
Här är en vy som returnerar aktuellt datum och tid, som ett HTML-dokument:
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = '<html lang="en"><body>It is now %s.</body></html>' % now
return HttpResponse(html)
Låt oss gå igenom koden en rad i taget:
Först importerar vi klassen
HttpResponse
från modulendjango.http
, tillsammans med Pythons bibliotekdatetime
.Därefter definierar vi en funktion som heter
current_datetime
. Detta är en vyfunktion. Varje view-funktion tar ettHttpRequest
-objekt som sin första parameter, som vanligtvis heterrequest
.Observera att namnet på vyfunktionen inte spelar någon roll; den behöver inte namnges på ett visst sätt för att Django ska känna igen den. Vi kallar den
current_datetime
här, eftersom det namnet tydligt anger vad den gör.Vyn returnerar ett
HttpResponse
-objekt som innehåller det genererade svaret. Varje vyfunktion är ansvarig för att returnera ettHttpResponse
-objekt. (Det finns undantag, men dem kommer vi till senare)
Djangos tidszon
Django innehåller en TIME_ZONE
-inställning som standard är Amerika/Chicago
. Detta är förmodligen inte där du bor, så du kanske vill ändra det i din inställningsfil.
Mappning av webbadresser till vyer¶
Sammanfattningsvis returnerar denna vyfunktion en HTML-sida som innehåller aktuellt datum och aktuell tid. Om du vill visa den här vyn på en viss URL måste du skapa en URLconf; se URL-distributör för instruktioner.
Returnera fel¶
Django tillhandahåller hjälp för att returnera HTTP-felkoder. Det finns underklasser av HttpResponse
för ett antal vanliga HTTP-statuskoder andra än 200 (vilket betyder ”OK”). Du kan hitta den fullständiga listan över tillgängliga underklasser i :ref:``request/response <ref-httpresponse-subclasses>`-dokumentationen. Returnera en instans av en av dessa underklasser istället för en normal HttpResponse
för att indikera ett fel. Till exempel:
from django.http import HttpResponse, HttpResponseNotFound
def my_view(request):
# ...
if foo:
return HttpResponseNotFound("<h1>Page not found</h1>")
else:
return HttpResponse("<h1>Page was found</h1>")
Det finns inte en specialiserad underklass för varje möjlig HTTP-svarskod, eftersom många av dem inte kommer att vara så vanliga. Men som dokumenterat i HttpResponse
-dokumentationen kan du också skicka HTTP-statuskoden till konstruktören för HttpResponse
för att skapa en returklass för vilken statuskod du vill. Till exempel:
from django.http import HttpResponse
def my_view(request):
# ...
# Return a "created" (201) response code.
return HttpResponse(status=201)
Eftersom 404-fel är det överlägset vanligaste HTTP-felet finns det ett enklare sätt att hantera dessa fel.
Undantaget ”Http404¶
- class django.http.Http404¶
När du returnerar ett fel som HttpResponseNotFound
, är du ansvarig för att definiera HTML på den resulterande felsidan:
return HttpResponseNotFound("<h1>Page not found</h1>")
För enkelhetens skull, och eftersom det är en bra idé att ha en konsekvent 404-felsida på hela webbplatsen, tillhandahåller Django ett undantag för Http404
. Om du höjer Http404
vid någon tidpunkt i en vyfunktion, kommer Django att fånga det och returnera standardfelsidan för din applikation, tillsammans med en HTTP-felkod 404.
Exempel på användning:
from django.http import Http404
from django.shortcuts import render
from polls.models import Poll
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404("Poll does not exist")
return render(request, "polls/detail.html", {"poll": p})
För att visa anpassad HTML när Django returnerar en 404, kan du skapa en HTML-mall med namnet 404.html
och placera den på den översta nivån i ditt mallträd. Denna mall kommer sedan att visas när DEBUG
är inställd på False
.
När DEBUG
är True
kan du ange ett meddelande till Http404
och det kommer att visas i standardmallen för 404 debug. Använd dessa meddelanden i felsökningssyfte; de är i allmänhet inte lämpliga att använda i en 404-mall för produktion.
Anpassa felvyer¶
Standardfelvyerna i Django bör räcka för de flesta webbapplikationer, men kan enkelt åsidosättas om du behöver något anpassat beteende. Specificera hanterarna enligt nedan i din URLconf (att ställa in dem någon annanstans har ingen effekt).
Vyn page_not_found()
åsidosätts av handler404
:
handler404 = "mysite.views.my_custom_page_not_found_view"
Vyn server_error()
åsidosätts av handler500
:
handler500 = "mysite.views.my_custom_error_view"
Vyn permission_denied()
åsidosätts av handler403
:
handler403 = "mysite.views.my_custom_permission_denied_view"
Vyn bad_request()
åsidosätts av handler400
:
handler400 = "mysite.views.my_custom_bad_request_view"
Se även
Använd inställningen CSRF_FAILURE_VIEW
för att åsidosätta CSRF-felvyn.
Testa anpassade felvyer¶
Om du vill testa svaret från en anpassad felhanterare kan du skapa ett lämpligt undantag i en testvy. Till exempel:
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.test import SimpleTestCase, override_settings
from django.urls import path
def response_error_handler(request, exception=None):
return HttpResponse("Error handler content", status=403)
def permission_denied_view(request):
raise PermissionDenied
urlpatterns = [
path("403/", permission_denied_view),
]
handler403 = response_error_handler
# ROOT_URLCONF must specify the module that contains handler403 = ...
@override_settings(ROOT_URLCONF=__name__)
class CustomErrorHandlerTests(SimpleTestCase):
def test_handler_renders_template_response(self):
response = self.client.get("/403/")
# Make assertions on the response here. For example:
self.assertContains(response, "Error handler content", status_code=403)
Asynkrona vyer¶
Förutom att vara synkrona funktioner kan vyer också vara asynkrona (”async”) funktioner, normalt definierade med Pythons async def
syntax. Django kommer automatiskt att upptäcka dessa och köra dem i ett asynkront sammanhang. Du måste dock använda en asynkron server baserad på ASGI för att få prestandafördelarna.
Här är ett exempel på en asynkron vy:
import datetime
from django.http import HttpResponse
async def current_datetime(request):
now = datetime.datetime.now()
html = '<html lang="en"><body>It is now %s.</body></html>' % now
return HttpResponse(html)
Du kan läsa mer om Djangos async-stöd, och hur du bäst använder async-vyer, i Asynkront stöd.