Introducere

Class-Based Views oferă o alternativă pentru implementarea view-urilor. Față de definirea acestora sub formă de funcții, clasele oferă mai multe avantaje, printre care:

  • o organizare mai bună a codului
  • reutilizarea codului prin utilizarea procedeelor specifice programării orientate-obiect

Puteți citi mai multe aici.

Utilizarea class-based views

Fie dat următorul function-based view:

from django.http import HttpResponse

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

Pentru a-l transforma într-un class-based view, trebuie definită o clasă ce moștenește unul din următoarele view-uri de bază:

Acestea oferă o mare parte din funcționalitatea necesară definirii view-urilor. De asemenea, request-ul trebuie tratat într-o metodă.

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

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

Totuși, Django se așteaptă să trimită un anumit request la o funcție, nu la o clasă. Pentru a rezolva acestă problemă, class-based views au implementată o metodă as_view() ce returnează funcția potrivită request-ului respectiv (în acest caz metoda get a clasei MyView) .

Astfel url-ul va fi declarat în următorul mod:

url(r'^about/$', MyView.as_view())

Utilizarea formularelor în class-based views

În primul exemplu este prezentat modul în care sunt tratate formularele în function-based views.

Function based view:

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})

Class-based view:

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})

În class-based views formularul poate fi reținut într-un atribut și preluat de acolo. În cazul schimbării formularului, înlocuirea acestuia ar fi mult mai ușoară.

Mai multe aici.

Decoratori

Decoratorii nu sunt limitați numai la funcții. Aceștia pot fi utilizați și în cazul claselor.

Există două metode prin care acestea pot fi decorate:

  • Decorare în URLconf

      urlpatterns = [
          url(r'^about/$', login_required(TemplateView.as_view(template_name="secret.html"))),
      ]
    
  • Decorarea clasei

    Pentru a aplica un decorator pe o metodă, acesta trebuie transformat mai întâi într-un decorator pentru metode. Acest lucru se realizează apelând method_decorator având ca parametru decoratorul dorit. Decoratorul obținut trebuie aplicat pe metoda dispatch a clasei.

    Acest lucru se poate realiza fie punând decoratorul înainte de metodă sau înaintea clasei:

    class ProtectedView(TemplateView):
        template_name = 'secret.html'
    
        @method_decorator(login_required)
        def dispatch(self, *args, **kwargs):
            return super(ProtectedView, self).dispatch(*args, **kwargs)
    

    sau

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

Mixins

Mixins sunt o formă de moștenire multiplă. Acestea sunt folositoare pentru a obține comportamentul dorit pentru view cu cât mai puțin cod, utilizând din fiecare clasă moștenită atribute sau metode.

Aici găsiți o listă cu acestea.

Generic views

Moștenind aceste view-uri se pot efectua operatii uzuale(listarea obiectelor, listarea detaliilor unui singur obiect etc) în puține linii de cod.

Principalele view-uri generice oferite de Django sunt:

View-urile de vizualizare:

View-urile de modificare:

Să presupunem că avem următorul model:

class Person(models.Model):
    name = models.CharField(max_length=100)
    gender = models.CharField(max_length=30)

Vom defini un view ce va lista toate persoanele din baza de date, utilizand view-ul generic ListView

# views.py
from django.views.generic import ListView
from models import Person

class PersonList(ListView):
    model = Person

Se adaugă view-ul și în urls

from django.conf.urls import url
from books.views import PersonList

urlpatterns = [
    url(r'^persons/$', PersonList.as_view()),
]