Zapraszam do kolejnego z serii postów opisujących widoki klasowe w Django (Class Based Views). Jest to rozwinięcie webinaru, w którym pokazałem jak szybko zbudować stronę internetową z wykorzystaniem CBV: Django w godzinę: Tworzenie aplikacji z Class Based Views.
W poprzednim poście Django Class Based Views: Wprowadzenie i porównanie z widokami funkcyjnymi opisałem podstawowe różnice pomiędzy widokami funkcyjnymi i klasowymi. W mojej opinii widoki klasowe są przyjaźniejsze i wymagają mniej kodu.
W tym poście omówię podstawowe widoki klasowe wraz z przykładami. Zapraszam do lektury!
Podstawowe widoki klasowe w Django.
Widoki klasowe w Django są oparte na mechanizmie dziedziczenia, co oznacza, że klasy widoków dziedziczą z podstawowej klasy o nazwie View
. Dzięki temu, tworzenie własnych widoków klasowych staje się prostsze i bardziej modułowe. Klasa View
jest bardzo uboga w konfiguracje czy działanie - obsługę metod get()
, post()
, put()
musimy napisać sami. Co więc daje? Niewiele, poza początkiem łańcucha dziedziczenia. Przykład użycia:
# views.py
from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self, request):
# <view logic>
return HttpResponse("result")
# urls.py
from django.urls import path
from myapp.views import MyView
urlpatterns = [
path("about/", MyView.as_view()),
]
Żródło: https://docs.djangoproject.com/en/4.2/topics/class-based-views/intro/#using-class-based-views
Metoda get_context_data
W kontekście widoków w Django, "context" odnosi się do danych przekazywanych z widoku do szablonu. Kontekst jest zwykle reprezentowany jako słownik, który zawiera informacje, takie jak zmienne, listy, obiekty modelu itp. Te dane są wykorzystywane do dynamicznego generowania treści w szablonie, umożliwiając personalizację i interakcję z użytkownikiem. Przekazywanie kontekstu zapewnia spójne przekazywanie informacji między widokiem a szablonem, umożliwiając tworzenie dynamicznych aplikacji webowych w Django.
Metoda get_context_data
umozliwia dodanie własnego kontekstu do szablonu. Co to oznacza w praktyce? Na przykład:
- w najprostszym TemplateView, który w domyśle nie ma niczego, możemy umieścić informacje o artykule.
- korzystając z dziedziczenia możemy dodać do każdego szablonu podstawowe informacje do wyświetlenia na każdej stronie, jak na przykład dane kontaktowe: numer telefonu i adres email w stopce.
# views.py
from django.views.generic import View, TemplateView
class DefaultContext(View):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# dodanie własnych wartości
context["email"] = "jacek@akademiait.com.pl"
context["wiadomość"] = "Masz pyania? Napisz do mnie!"
return context
# Teraz każdy widok dziedziczący z DefaultContext będzie miał od razu {{ email }}
# dostępny w szablonie
class Main(DefaultContext, TemplateView):
# ważna jest kolejność dziedziczenia, DefaultContext jest pierwszy.
template_name = "index.html"
{# index.html #}
{{email}}
żródło: Własne
Django posiada wiele rozwiniętych klas widoków, z których wszystkie dziedziczą z View
:
- TemplateView
- RedirectView
- DetailView
- ListView
- DeleteView
- CreateView
- FormView
- ArchiveIndexView, YearArchiveView, MonthArchiveView, WeekArchiveView, DayArchiveView, DateDetailView
Każdy z tych widoków posiada następujące parametry:
- template_name: nazwa szablonu, który będzie renderowany. Nie jest wymagana, Django potrafi samo stworzyć tę nazwę. Zdecydowanie polecam jednak ją jawnie deklarować - o wiele łatwiej się pracuje.
- template_engine - jaki rodzaj silnika ma być użyty do renderowania template. Parametr niewymagany.
- response_class - z jakiej klasy korzysta response. Parametr niewymagany. Jego wartość zależy od tego, z jakiej klasy widoku korzystamy.
- content_type - czyli jaki będzie
content_type
odpowiedzi. Czasem może to być na przykładapplication/json
, najczęściej klasycznytext/html
z odpowiednim kodowaniem znaków. Parametr przydatny gdy np. zwracamy plik do pobrania.
TemplateView
Widok podstawowy. W domyśle służy do tego, by wyświetlić szablon bez żadnych danych dodatkowych. Korzystając z get_context_data
można dodać do niego dowolne dane. Przydatny do serwisów typu wizytówka, gdzie mamy jedną stronę i sporo danych:
#views.py
class HomeView(TemplateView):
template_name = "home.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["offers"] = Offer.objects.all()
context["video"] = Video.objects.all()
context["contact"] = ContactData.objects.first()
...
return context
żródło: Własne
Wszystkie zadeklarowane powyżej zmienne w context
będą dostępne w szablonie do wyświetlenia.
RedirectView
Widok ten jest specjalnym typem widoku, który przekierowuje żądanie HTTP na inną stronę. Po otrzymaniu żądania, wykonuje przekierowanie na podaną ścieżkę URL, co powoduje przekierowanie przeglądarki użytkownika na nową stronę. Przydatne, gdy chcemy przekierować użytkownika po wykonaniu określonych akcji, np. zakończenie pewnego procesu zakupowego, na inną stronę w aplikacji. Lub gdy usunęliśmy stronę z serwera.
Posiada następujące parametry:
permanent
- czy przekierowanie jest stałe? Domyślnie ma wartośćFalse
. Ustawienie na True spowoduje, że przeglądarka zapamięta, że ten URL (A) kieruje na stronę B i więcej nie będzie pytać serwera o A. Jeśli wprowadzimy URL wskazujący A do paska adresu, przeglądarka sama przekieruje się do B. Czyli, dość niebezpiecznie jest ustawiaćpermanent=True
bo możemy zablokować sobie URLa na stałe.query_string = False
. Czy widok ma przekazać zawartość tablicy GET (czyli to, co jest po?
w URLu) do następnej strony? DomyślnieFalse
.url
do przekierowania. Parametr niewymagany!pattern_name
- nazwa wzorca adresu URL do przekierowania - czyliname
zurls.py
. Django samo zbuduje odpowiedni URL korzystając zargs
ikwargs
, czyli parametrów, przekazanych do obecnego widoku.
Dodatkowo klasa ta zawiera metodę get_redirect_url(*args, **kwargs)
, która pozwala zbudować URL do przekierowania, w dowolny sposób określony przez nas.
DetailView
Widok przeznaczony do wyświetlania danych, a dokładnie konkretnej instancji obiektu, na przykład artykułu.
# views.py
from django.utils import timezone
from django.views.generic.detail import DetailView
from articles.models import Article
class ArticleDetailView(DetailView):
model = Article
template = "article.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["now"] = timezone.now()
return context
żródło: https://docs.djangoproject.com/en/4.2/ref/class-based-views/generic-display/
Powyższy kod wyświetli nam artykuł. Dodatkowo w szablonie html będzie dostępna bieżąca data i czas.
{# article.html #}
<p>
Article jest dodany automatycznie przez Django i dostępny jako "object" w kontekście.
</p>
{{ object.title }}
{{ object.id }}
{{ now|date }}
żródło: Własne
Niektóre parametry i metody:
- model - czyli jakiego modelu obiekty mają być wyświetlone na stronie
- queryset - jakie zapytanie do bazy wykonać, by pobrać obiekt do wyświetlenia.
model
lubqueryset
jest wymagane. Żeby pobrać artykułqueryset = Article.objects.all()
- Django już samo dobierze sobie właściwy obiekt get_queryset(self)
- metoda, której możemy użyć zamiast obydwu powyższych opcji i po prostu zwrócić zapytanieget_object(self, *args, **kwargs)
- metoda, której również możemy użyć do zwrócenia danych dla szablonu. Ma zwrócić konkretny obiekt.- context_object_name - jakiej nazwy dla obiektu użyć w kontekście. Domyślnie, jak na listingu powyżej, Django używa
object
. Ten parametr pozwala na zdefiniowanie własnej nazwy np:context_object_name = "article"
. Wtedy w szablonie zamieniamyobject
naarticle
.
Powyżej wypisałem metody, moim zdaniem, najważniejsze. Powinny wystarczyć do większości zastosowań. Pozostałe, a jest ich sporo, można znaleźć w dokumentacji: https://docs.djangoproject.com/en/4.2/ref/class-based-views/mixins-single-object/#singleobjectmixin
To tyle na dzisiaj. Zależy mi, by przekazywać Wam wiedzę stopniowo. Zapraszam do zadawania pytań przez formularz kontaktowy. Oczywiście, proponuję też samemu poeksperymentować z kodem. Jeśli natomiast potrzebujesz indywidualnych konsultacji, zapraszam do mentoringu
Nie przegapcie kolejnych części tej serii, gdzie będę kontynuował opisywanie różnych widoków klasowych i dzielenie się cennymi wskazówkami dotyczącymi ich użycia.
Spodobał Ci się post?
Podziel się nim!
Masz uwagi do posta, chcesz porozmawiać, szukasz pomocy z Pythonem i Django? Napisz do mnie!
1 thought on “Class-Based Views w Django: Wygodny sposób tworzenia widoków, część 1.”
Comments are closed.