Django
Ogólne widoki
Szukaj…
Wprowadzenie
Widoki ogólne to widoki, które wykonują określoną z góry akcję, taką jak tworzenie, edytowanie lub usuwanie obiektów lub po prostu wyświetlanie szablonu.
Widoki ogólne należy odróżnić od widoków funkcjonalnych, które są zawsze pisane ręcznie w celu wykonania wymaganych zadań. W skrócie można powiedzieć, że widoki ogólne należy skonfigurować, a widoki funkcjonalne należy zaprogramować.
Widoki ogólne mogą zaoszczędzić dużo czasu, zwłaszcza gdy masz wiele standardowych zadań do wykonania.
Uwagi
Te przykłady pokazują, że ogólne widoki znacznie upraszczają znormalizowane zadania. Zamiast programować wszystko od zera, konfigurujesz to, co inni ludzie już dla Ciebie zaprogramowali. Ma to sens w wielu sytuacjach, ponieważ pozwala bardziej skoncentrować się na projektach, a nie na procesach w tle.
Czy zawsze powinieneś ich używać? Nie. Mają sens tylko, o ile Twoje zadania są dość standaryzowane (ładowanie, edycja, usuwanie obiektów) i im bardziej powtarzalne są twoje zadania. Użycie jednego określonego widoku ogólnego tylko raz, a następnie zastąpienie wszystkich jego metod w celu wykonania bardzo specyficznych zadań może nie mieć sensu. Tutaj może być lepiej z funkcjonalnym widokiem.
Jeśli jednak masz wiele widoków wymagających tej funkcji lub jeśli twoje zadania dokładnie pasują do zdefiniowanych zadań określonego widoku ogólnego, wówczas widoki ogólne są dokładnie tym, czego potrzebujesz, aby ułatwić Ci życie.
Minimalny przykład: widoki funkcjonalne vs. ogólne
Przykład funkcjonalnego widoku do utworzenia obiektu. Bez komentarzy i pustych wierszy potrzebujemy 15 wierszy kodu:
# imports
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from .models import SampleObject
from .forms import SampleObjectForm
# view functioon
def create_object(request):
# when request method is 'GET', show the template
if request.method == GET:
# perform actions, such as loading a model form
form = SampleObjectForm()
return render_to_response('template.html', locals())
# if request method is 'POST', create the object and redirect
if request.method == POST:
form = SampleObjectForm(request.POST)
# save object and redirect to success page if form is valid
if form.is_valid:
form.save()
return HttpResponseRedirect('url_to_redirect_to')
# load template with form and show errors
else:
return render_to_response('template.html', locals())
Przykład „Ogólnego widoku opartego na klasach” w celu wykonania tego samego zadania. Potrzebujemy tylko 7 linii kodu, aby osiągnąć to samo zadanie:
from django.views.generic import CreateView
from .models import SampleObject
from .forms import SampleObjectForm
class CreateObject(CreateView):
model = SampleObject
form_class = SampleObjectForm
success_url = 'url_to_redirect_to'
Dostosowywanie widoków ogólnych
Powyższy przykład działa tylko wtedy, gdy twoje zadania są całkowicie standardowe. Na przykład nie dodajesz dodatkowego kontekstu.
Zróbmy bardziej realistyczny przykład. Załóżmy, że chcemy dodać tytuł strony do szablonu. W widoku funkcjonalnym działałoby to tak - z tylko jedną dodatkową linią:
def create_object(request):
page_title = 'My Page Title'
# ...
return render_to_response('template.html', locals())
Jest to trudniejsze (lub: przeciwne do intuicyjnego) do osiągnięcia w przypadku widoków ogólnych. Ponieważ są one oparte na klasach, należy zastąpić jedną lub kilka metod klasy, aby osiągnąć pożądany wynik. W naszym przykładzie musimy przesłonić klasową metodę get_context_data w następujący sposób:
class CreateObject(CreateView):
model = SampleObject
form_class = SampleObjectForm
success_url = 'url_to_redirect_to'
def get_context_data(self, **kwargs):
# Call class's get_context_data method to retrieve context
context = super().get_context_data(**kwargs)
context['page_title'] = 'My page title'
return context
Tutaj potrzebujemy czterech dodatkowych wierszy do zakodowania zamiast tylko jednego - przynajmniej dla pierwszej dodatkowej zmiennej kontekstowej, którą chcemy dodać.
Ogólne widoki z Mixins
Prawdziwa moc ogólnych widoków ujawnia się, gdy połączysz je z Mixinami. Mixin to kolejna zdefiniowana przez ciebie klasa, której metody mogą być dziedziczone przez twoją klasę widoku.
Załóżmy, że chcesz, aby każdy widok wyświetlał dodatkową zmienną „page_title” w szablonie. Zamiast przesłonić metodę get_context_data za każdym razem, gdy definiujesz widok, tworzysz mixin za pomocą tej metody i pozwalasz, aby twoje widoki dziedziczyły po tym mixinie. Brzmi bardziej skomplikowane niż jest w rzeczywistości:
# Your Mixin
class CustomMixin(object):
def get_context_data(self, **kwargs):
# Call class's get_context_data method to retrieve context
context = super().get_context_data(**kwargs)
context['page_title'] = 'My page title'
return context
# Your view function now inherits from the Mixin
class CreateObject(CustomMixin, CreateView):
model = SampleObject
form_class = SampleObjectForm
success_url = 'url_to_redirect_to'
# As all other view functions which need these methods
class EditObject(CustomMixin, EditView):
model = SampleObject
# ...
Piękno tego polega na tym, że kod staje się znacznie bardziej uporządkowany niż w przypadku widoków funkcjonalnych. Cała logika stojąca za konkretnymi zadaniami znajduje się w jednym miejscu i tylko w jednym miejscu. Zaoszczędzisz także ogromną ilość czasu, zwłaszcza gdy masz wiele widoków, które zawsze wykonują te same zadania, z wyjątkiem różnych obiektów