Widoki generyczne

Widoki generyczne, czyli ogólne, w Django zostały napisane, by urzeczywistniać zasadę DRY, tj niepowtarzania tych samych czynności.
Budowa kontrolerów, zwanych w Django widokami, jest bowiem dla większości stron webowych podobna, a więc jest możliwe stworzenie abstrakcyjnego, ogólnego kodu, który będzie mógł być zastosowany zawsze wtedy, gdy spełnione są pewne założenia.
Okazuje się napisanie takiego kodu jest możliwe, został on napisany i jest możliwy do wykorzystania z Django.

Konkretnie Django dostarcza widoki "ogólne", które mogą wykonywać następujące zadania:

  • Przekierowanie do innej strony, renderowanie konkretnego szablonu
  • Wyświetlanie listy obiektów danego modelu oraz szczegółów każdego takiego obiektu. Klasycznym przykładem umożliwiającym zastosowanie tego rozwiązania jest wyświetlanie listy wpisów w blogu oraz całości każdego wpisu
  • Prezentacja obiektów opartych na datach, takich jak miesięczne czy roczne archiwa wpisów
  • Wykonywanie operacji typu CRUD

Jedną z ciekawszych właściwości widoków ogólnych Django jest to, że mogą one być używane na dwa sposoby.
Po pierwsze można dzięki nim zbudować aplikację nie pisząc w ogóle funkcji widoku. Informację o skorzystaniu z widoku generycznego umieszczamy w wtedy w urls.py. Oto przykład najprostszej sytuacji tego typu - napisaliśmy statyczną stronę i umieściliśmy jej kod html w pliku strona.html. Sytuacja taka jest całkiem realna - w każdej niemal aplikacji zdarzają się strony, które będą modyfikowane rzadko lub prawie wcale. Czasami w takich sytuacjach nie warto ich wpisaywać do bazy danych. Istnieje widok generyczny direct_to_template, który pozwala taką stronę wyświetlić. Załóżmy, że chcemy, żeby URL do naszej strony nazywał się http://jakas-domena.com/nasza-strona-statyczna/. Możemy więc w urls.py napisać:

from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
 
urlpatterns = patterns('',
     r('^nasza-strona-statyczna/$', direct_to_template, {
        'template': 'strona.html'
    })
)

Jest to w zasadzie cała, kompletna, aplikacja Django - chyba najprostsza jaką możemy sobie wyobrazić.

Teraz drugi przykład. W tej samej dokładnie sytuacji chcemy jednak z jakichś powodów napisać własną funkcję widoku. Nie ma problemu, w pliku views.py wpisujemy:

from django.views.generic.simple import direct_to_template
 
def static_page(request):
    return direct_to_template(request, template="strona.html")

Ten kod jest rzeczywiście prosty (i działa!), ale... wrażliwy na błędy i dlatego nieelegancki, poza tym nie daje nam zbyt wielu możliwości. Rozbudujmy go więc trochę.

from django.http import Http404
from django.template import TemplateDoesNotExist
from django.views.generic.simple import direct_to_template
 
def static_page(request, page):
    try:
        return direct_to_template(request, template="%s.html" % page)
    except TemplateDoesNotExist:
        raise Http404()

Po pierwsze zabezpieczamy się w ten sposób przez błędem nieistniejącego szablonu. Decydujemy, że ma się w takiej sytuacji wyświetlić strona błędu 404, co jest rozsądne, bo przecież na szablon jest po prostu statyczną stroną. Po drugie, nasza funkcja widoku przyjmuje drugi parametr - page. Zobaczmy jak urls.py może przekazać wartość tego parametru, i zależnie od tego zostanie wybrana jedna ze statycznych stron:

from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
from mysite.books.views import about_pages
 
urlpatterns = patterns('',
    r('^nasza-strona-statyczna/(w+)/$', static_page),
)

Znów mamy powyżej pełną aplikację Django. Fakt, że nadal banalną, bo do wyświetlania statycznych stron według URL nie potrzeba Django... ale chodzi o zasadę działania generycznych widoków, która w niebanalnych przypadkach pozostaje dokładnie taka sama.

Ciąg dalszy nastąpi ;)