# Django 6.0.7 documentation

# Introduktion till klassbaserade vyer

Klassbaserade vyer är ett alternativt sätt att implementera vyer som Python-objekt i stället för funktioner. De ersätter inte funktionsbaserade vyer, men har vissa skillnader och fördelar jämfört med funktionsbaserade vyer:

- Organisering av kod relaterad till specifika HTTP-metoder (`GET`, `POST`, etc.) kan hanteras med separata metoder istället för villkorlig förgrening.

- Objektorienterade tekniker som mixins (multiple inheritance) kan användas för att dela upp koden i återanvändbara komponenter.

## Förhållandet mellan och historien bakom generiska vyer, klassbaserade vyer och klassbaserade generiska vyer

I början fanns det bara view-funktionskontraktet, Django skickade din funktion en `HttpRequest` och förväntade sig tillbaka en `HttpResponse`. Detta var omfattningen av vad Django tillhandahöll.

Redan tidigt insåg man att det fanns vanliga idiom och mönster i utvecklingen av vyer. Funktionsbaserade generiska vyer introducerades för att abstrahera dessa mönster och underlätta utvecklingen av vyer för de vanligaste fallen.

Problemet med funktionsbaserade generiska vyer är att de visserligen täcker de enkla fallen väl, men att det inte finns något sätt att utöka eller anpassa dem utöver vissa konfigurationsalternativ, vilket begränsar deras användbarhet i många verkliga tillämpningar.

Klassbaserade generiska vyer skapades med samma mål som funktionsbaserade generiska vyer, att göra det enklare att utveckla vyer. Det sätt på vilket lösningen implementeras, genom användning av mixins, ger dock en verktygslåda som resulterar i att klassbaserade generiska vyer är mer utbyggbara och flexibla än sina funktionsbaserade motsvarigheter.

Om du tidigare har provat funktionsbaserade generiska vyer och funnit dem otillräckliga, bör du inte se klassbaserade generiska vyer som en klassbaserad motsvarighet, utan snarare som ett nytt sätt att lösa de ursprungliga problem som generiska vyer var avsedda att lösa.

Verktygslådan med basklasser och mixins som Django använder för att bygga klassbaserade generiska vyer är byggd för maximal flexibilitet och har därför många hooks i form av standardmetoderealiseringar och attribut som du troligen inte kommer att bry dig om i de enklaste användningsfallen. I stället för att begränsa dig till ett klassbaserat attribut för `form_class` använder implementeringen till exempel en `get_form`-metod, som anropar en `get_form_class`-metod, som i sin standardimplementering returnerar klassens `form_class`-attribut. Detta ger dig flera alternativ för att ange vilket formulär som ska användas, från ett attribut till en helt dynamisk, anropsbar hook. Dessa alternativ verkar lägga till ihålig komplexitet för enkla situationer, men utan dem skulle mer avancerade mönster vara begränsade.

## Använda klassbaserade vyer

I grunden innebär en klassbaserad vy att du kan svara på olika HTTP-begärandemetoder med olika klassinstansmetoder, istället för med villkorligt förgrenad kod i en enda vyfunktion.

Så där koden för att hantera HTTP `GET` i en vyfunktion skulle se ut ungefär som:

    from django.http import HttpResponse

    def my_view(request):
        if request.method == "GET":
            # <view logic>
            return HttpResponse("result")

I en klassbaserad vy skulle detta bli:

    from django.http import HttpResponse
    from django.views import View

    class MyView(View):
        def get(self, request):
            # <view logic>
            return HttpResponse("result")

Eftersom Djangos URL-resolver förväntar sig att skicka begäran och tillhörande argument till en anropbar funktion, inte en klass, har klassbaserade vyer en klassmetod `as_view()` som returnerar en funktion som kan anropas när en begäran kommer för en URL som matchar det associerade mönstret. Funktionen skapar en instans av klassen, anropar `setup()` för att initialisera dess attribut och anropar sedan dess `dispatch()`-metod. `dispatch` tittar på begäran för att avgöra om det är en `GET`, `POST`, etc, och vidarebefordrar begäran till en matchande metod om en sådan är definierad, eller ger upphov till `HttpResponseNotAllowed` om inte:

    # urls.py
    from django.urls import path
    from myapp.views import MyView

    urlpatterns = [
        path("about/", MyView.as_view()),
    ]

Det är värt att notera att det som din metod returnerar är identiskt med det som du returnerar från en funktionsbaserad vy, nämligen någon form av `HttpResponse`. Detta innebär att http shortcuts eller `TemplateResponse`-objekt är giltiga att använda i en klassbaserad vy.

Även om en minimal klassbaserad vy inte kräver några klassattribut för att utföra sitt jobb, är klassattribut användbara i många klassbaserade designer, och det finns två sätt att konfigurera eller ange klassattribut.

Den första är det vanliga Python-sättet att subklassa och åsidosätta attribut och metoder i subklassen. Så om din överordnade klass hade ett attribut `greeting` så här:

    from django.http import HttpResponse
    from django.views import View

    class GreetingView(View):
        greeting = "Good Day"

        def get(self, request):
            return HttpResponse(self.greeting)

Du kan åsidosätta det i en subklass:

    class MorningGreetingView(GreetingView):
        greeting = "Morning to ya"

Ett annat alternativ är att konfigurera klassattribut som nyckelordsargument till `as_view()`-anropet i URLconf:

    urlpatterns = [
        path("about/", GreetingView.as_view(greeting="G'day")),
    ]

Observera

Medan din klass instansieras för varje begäran som skickas till den, konfigureras klassattribut som anges via `as_view()`-ingångspunkten endast en gång vid den tidpunkt då dina webbadresser importeras.

## Använda mixins

Mixins är en form av multipel nedärvning där beteenden och attribut från flera överordnade klasser kan kombineras.

Till exempel finns det i de generiska klassbaserade vyerna en mixin som heter `TemplateResponseMixin` vars primära syfte är att definiera metoden `render_to_response()`. I kombination med beteendet i basklassen `View` blir resultatet en klass av typen `TemplateView` som skickar förfrågningar till lämpliga matchningsmetoder (ett beteende som definieras i basklassen `View`) och som har en `render_to_response()`-metoden som använder ett `template_name`-attribut för att returnera ett `TemplateResponse`-objekt (ett beteende som definieras i `TemplateResponseMixin`).

Mixins är ett utmärkt sätt att återanvända kod i flera klasser, men de har ett visst pris. Ju mer din kod är utspridd bland mixins, desto svårare blir det att läsa en underordnad klass och veta exakt vad den gör, och desto svårare blir det att veta vilka metoder från vilka mixins som ska åsidosättas om du subklassar något som har ett djupt arvsträd.

Observera också att du bara kan ärva från en generisk vy - det vill säga, bara en föräldraklass kan ärva från `View` och resten (om någon) bör vara mixins. Att försöka ärva från mer än en klass som ärver från `View` - till exempel att försöka använda ett formulär högst upp i en lista och kombinera `ProcessFormView` och `ListView` - kommer inte att fungera som förväntat.

## Hantera formulär med klassbaserade vyer

En grundläggande funktionsbaserad vy som hanterar formulär kan se ut ungefär så här:

    from django.http import HttpResponseRedirect
    from django.shortcuts import render

    from .forms import MyForm

    def myview(request):
        if request.method == "POST":
            form = MyForm(request.POST)
            if form.is_valid():
                # <process form cleaned data>
                return HttpResponseRedirect("/success/")
        else:
            form = MyForm(initial={"key": "value"})

        return render(request, "form_template.html", {"form": form})

En liknande klassbaserad vy kan se ut på följande sätt:

    from django.http import HttpResponseRedirect
    from django.shortcuts import render
    from django.views import View

    from .forms import MyForm

    class MyFormView(View):
        form_class = MyForm
        initial = {"key": "value"}
        template_name = "form_template.html"

        def get(self, request, *args, **kwargs):
            form = self.form_class(initial=self.initial)
            return render(request, self.template_name, {"form": form})

        def post(self, request, *args, **kwargs):
            form = self.form_class(request.POST)
            if form.is_valid():
                # <process form cleaned data>
                return HttpResponseRedirect("/success/")

            return render(request, self.template_name, {"form": form})

Detta är ett minimifall, men du kan se att du då skulle ha möjlighet att anpassa den här vyn genom att åsidosätta något av klassattributen, t.ex. `form_class`, via URLconf-konfiguration, eller subklassa och åsidosätta en eller flera av metoderna (eller båda!).

## Dekorera klassbaserade vyer

Utökningen av klassbaserade vyer är inte begränsad till att använda mixins. Du kan också använda dekoratorer. Eftersom klassbaserade vyer inte är funktioner fungerar dekorering av dem olika beroende på om du använder `as_view()` eller skapar en subklass.

### Dekorera i URLconf

Du kan justera klassbaserade vyer genom att dekorera resultatet av `as_view()`-metoden. Det enklaste stället att göra detta är i URLconf där du distribuerar din vy:

    from django.contrib.auth.decorators import login_required, permission_required
    from django.views.generic import TemplateView

    from .views import VoteView

    urlpatterns = [
        path("about/", login_required(TemplateView.as_view(template_name="secret.html"))),
        path("vote/", permission_required("polls.can_vote")(VoteView.as_view())),
    ]

Denna metod tillämpar dekoratorn per instans. Om du vill att varje instans av en vy ska dekoreras måste du använda ett annat tillvägagångssätt.

### Inredning av klassen

För att dekorera varje instans av en klassbaserad vy måste du dekorera själva klassdefinitionen. För att göra detta tillämpar du dekoratorn på klassens `dispatch()`-metod.

En metod i en klass är inte riktigt samma sak som en fristående funktion, så du kan inte bara använda en funktionsdekorator på metoden - du måste först omvandla den till en metoddekorator. Dekoratorn `method_decorator` omvandlar en funktionsdekorator till en metoddekorator så att den kan användas på en instansmetod. Till exempel:

    from django.contrib.auth.decorators import login_required
    from django.utils.decorators import method_decorator
    from django.views.generic import TemplateView

    class ProtectedView(TemplateView):
        template_name = "secret.html"

        @method_decorator(login_required)
        def dispatch(self, *args, **kwargs):
            return super().dispatch(*args, **kwargs)

Eller, mer kortfattat, du kan dekorera klassen istället och skicka namnet på den metod som ska dekoreras som nyckelordsargumentet `name`:

    @method_decorator(login_required, name="dispatch")
    class ProtectedView(TemplateView):
        template_name = "secret.html"

Om du har en uppsättning vanliga dekoratorer som används på flera ställen kan du definiera en lista eller tupel av dekoratorer och använda detta istället för att anropa `method_decorator()` flera gånger. Dessa två klasser är likvärdiga:

    decorators = [never_cache, login_required]

    @method_decorator(decorators, name="dispatch")
    class ProtectedView(TemplateView):
        template_name = "secret.html"

    @method_decorator(never_cache, name="dispatch")
    @method_decorator(login_required, name="dispatch")
    class ProtectedView(TemplateView):
        template_name = "secret.html"

Dekoratörerna behandlar en begäran i den ordning som de skickas till dekoratören. I exemplet kommer `never_cache()` att bearbeta begäran före `login_required()`.

I det här exemplet kommer varje instans av `ProtectedView` att ha inloggningsskydd. Dessa exempel använder `login_required`, men samma beteende kan erhållas genom att använda `LoginRequiredMixin`.

Observera

`method_decorator` skickar `*args` och `**kwargs` som parametrar till den dekorerade metoden på klassen. Om din metod inte accepterar en kompatibel uppsättning parametrar kommer den att ge upphov till ett `TypeError` undantag.