Kilka wydań temu zaprezentowaliśmy framework Ruby On Rails. Trudno się dziwić jego popularności wśród wielu webdeveloperów. Jego zalety są bowiem oczywiste – pozwala łatwo i szybko tworzyć nawet bardzo rozbudowane aplikacje internetowe. Okazuje się jednak, że RoR ma silną konkurencję. I to nie tylko w postaci omawianego w tym numerze Zend Framework, ale także frameworków stworzonych w Pythonie. Wśród tych ostatnich prym wiedzie Django.
W poprzednim numerze przybliżyliśmy język Python – w pełni obiektowy, zwięzły i za sprawą licznych bibliotek szeroko dostosowany do zastosowań internetowych. Wszystko po to, aby teraz przejść do omówienia jednego z frameworków napisanych w tym języku.
Bo choć ciężko odmówić Ruby On Rails licznych zalet, to nawet jego sympatycy muszą przyznać, że inne technologie nie pozostają w tyle. O ile licznie pojawiające się frameworki w PHP wciąż są dość młode, a te stworzone w oparciu o Javę wymagają specyficznego środowiska systemowego, to dla programistów Pythona od dawna dostępna jest ciekawa alternatywa w postaci frameworków Django oraz Pylons.
W niniejszym artykule postanowiliśmy skoncentrować się na pierwszym z nich. Django jest łatwiejsze w nauce od Pylons i pozwala szybciej tworzyć proste aplikacje, choć przy bardziej złożonych projektach może nieco ograniczać.
W żadnym razie jednak artykuł ten nie ma za zadanie przekonywać o wyższości Django nad Ruby On Rails lub odwrotnie. Trzeba przyznać, że źródła fenomenu tego drugiego leżą w tworzącym i wspierającym go środowisku programistów. O RoR dużo słychać na konferencjach, wydawanych jest wiele książek jemu poświęconych (w Polsce nie wydano dotąd żadnej na temat Django), także w internecie łatwiej znaleźć dokumentację i poradniki, jak również uzyskać pomoc na specjalistycznych forach internetowych. Programistów RoR jest po prostu więcej.
RoR ma także przewagę w postaci większej ilości wbudowanych mechanizmów oraz dodatków o większej funkcjonalności. Wynika to z faktu, że filozofia Django wymaga utrzymywania frameworka w zwartych ryzach i wykorzystywania jedynie własnych, natywnych rozwiązań. Rozszerzeń powstaje więc mniej, często nie są też one aż tak funkcjonalne. Może mieć to duże znaczenie przy bardziej złożonych projektach.
Wydawać by się mogło, że są to argumenty w zasadzie deklasujące Django w porównaniu z Ruby On Rails. Czy słusznie? W rzeczywistości ważne jest dobranie właściwego rozwiązania do potrzeb. Są bowiem kwestie, które w Django zostały rozwiązane bardzo dobrze, a w wielu przypadkach także jego mniejsza złożoność może przemawiać na korzyść tego systemu.
Ogromną zaletą Django jest jego prostota, dostępność widoków generycznych (które jeszcze bardziej przyspieszają tworzenie aplikacji) oraz samoistnie tworzący się panel administracyjny. To ostatnie sprawia, że Django wydaje się być świetnym rozwiązaniem dla wszelkiego rodzaju systemów zarządzania zawartością (serwisy informacyjne, blogi, sklepy internetowe).
Wydajność frameworków
Istnieje jeszcze jeden bardzo potężny argument przemawiający na korzyść Django. Ruby On Rails jest frameworkiem bardzo zasobożernym, co istotnie wpływa na koszty tworzonych w nim projektów. Sytuację pogarsza dodatkowo fakt, iż RoR wymaga korzystania ze specyficznych serwerów aplikacji, które na dodatek same w sobie nie są zoptymalizowane pod kątem wydajnościowym.
Wystarczy wspomnieć, że aktualnie najbardziej polecany przez środowisko RoR serwer aplikacji – Mongrel – nie posiada nawet wsparcia dla wielowątkowości. Wymusza to tworzenie kilku procesów dla każdego większego projektu, w przeciwnym razie kolejne połączenie z serwerem musiałoby oczekiwać na zakończenie poprzedniego zapytania – co byłoby wyraźnie odczuwalne dla użytkowników.
Jeśli dodać do tego fakt, że pojedynczy proces dedykowany określonemu projektowi nie zajmuje mniej niż 40 MB pamięci RAM (często dużo więcej), a procesy takie muszą być tworzone praktycznie niezależnie dla każdego uruchomionego projektu to otrzymujemy wyobrażenie o niemałych obciążeniach systemowych takiego rozwiązania. Nie lepiej jest zresztą także ze zużyciem czasu procesora aplikacji korzystających z RoR.
W przypadku Django sprawa wygląda inaczej. Wprawdzie sam framework również jest aplikacją dosyć złożoną (bez porównania bardziej niż prosty skrypt PHP wywołujący kilka zapytań do bazy danych), jednak korzysta on już z bardziej standardowych rozwiązań systemowych – istnieją wdrożenia Django opierające się o FastCGI czy nawet wbudowany moduł serwera Apache.
Pod względem środowiska, hostowanie Django jest więc analogiczne do przygotowania rozwiązania pod PHP. Dodatkowo jeden dedykowany Django proces może obsługiwać wiele projektów równocześnie. Jedynym ograniczeniem jest konieczność separowanie użytkowników systemu (dwaj użytkownicy hostingu współdzielonego nie mogą korzystać z tego samego procesu ze względów bezpieczeństwa).
Wszystko to sprawia, że hosting Django jest mniej skomplikowany od analogicznej usługi przeznaczonej dla Ruby On Rails. Jeśli przyrównać Django do niektórych bardziej złożonych aplikacji PHP, może się również okazać, że atut wydajności będzie po stronie Django. Framework ten narzuca bowiem programiście konieczność trzymania się dobrych praktyk programistycznych, podczas gdy skrypty PHP są często pisane w nie najlepszym stylu.
W teorii Django ze względu na łatwiejszą i mniej kłopotliwą konfigurację powinien być również bardziej powszechny wśród dostawców hostingu niż ma się to w przypadku RoR. Praktyka jest jednak nieco inna. Ze względu na niskie zainteresowanie ze strony programistów, nie ma na polskim rynku wielu providerów oferujących wsparcie dla Django, a ci którzy są – obsługują również RoR.
Organizacja projektów Django
Django jest frameworkiem stworzonym wokół wzorca MVC (Model-View-Controller), który zakłada odseparowanie od siebie trzech warstw: danych, logiki biznesowej oraz prezentacji. O samym MVC i jego zaletach wielokrotnie pisaliśmy na łamach Internet Makera. Dlatego nasi czytelnicy dobrze wiedzą, że taki sposób projektowania aplikacji ma wiele zalet.
W rzeczywistości w Django stosowana jest terminologia różniąca się od MVC, choć skupiona wokół tej samej idei. Django operuje na wzorcu Model-View-Template. Model odpowiada za obsługę struktur danych (w tym ich mapowanie w systemie bazodanowym), widok (ang. view) to miejsce tworzenia właściwej logiki biznesowej – zachowania aplikacji, podczas gdy wbudowany system szablonów (ang. template) pozwala zadbać o właściwą prezentację informacji wyprodukowanych przez widok.
Nadrzędną zasadą Django – podobnie jak wielu innych frameworków – jest zasada DRY, czyli Don’t Repeat Yourself. Zgodnie z tą regułą konieczne działania dokonuje się tylko w jednym, najwłaściwszym do tego miejscu, by później po prostu korzystać z wykonanej wcześniej pracy.
Zaletą korzystania z frameworków jest również narzucenie określonego porządku w kodzie. Każdy element aplikacji posiada swoje ściśle określone miejsce. Nadrzędną jednostką organizacyjną w Django jest projekt – gdy wydasz polecenie tworzące nowy projekt, zostanie utworzony katalog wraz z podstawową strukturą plików projektu. Na poziomie projektu obsługiwane są w szczególności połączenia z bazą danych i inne ogólne elementy konfiguracyjne. Warto w tym miejscu zaznaczyć, że Django potrafi komunikować się jedynie z jedną bazą danych w ramach pojedynczego projektu (do wyboru MySQL, PostgreSQL, Microsoft SQL oraz SQLite).
Projekt jest jednak tylko pewną ramą dla systemu, który zamierzasz stworzyć. W nim samym nie jest definiowana żadna konkretna funkcjonalność. Jest to domeną tzw. aplikacji (wyodrębnioną fizycznie jako podkatalog w folderze projektu). Aplikacja powinna całościowo odpowiadać za realizację narzuconych jej celów, korzystając z właściwych sobie modeli danych i widoków. Powinna być autonomiczna funkcjonalnie. W ramach projektu można umieszczać wiele aplikacji, podobnie jak poprawnie stworzoną aplikację powinieneś móc w dowolnym momencie przenieść do innego projektu i w nim użyć.
Jak to wygląda w praktyce? W artykule pokazujemy w jaki sposób możesz stworzyć prosty system blogowy. Projektem jest więc blog. Podstawowa aplikacja odpowiada za gromadzenie i wyświetlanie jego zawartości – wpisów na blogu (notek), wraz z informacjami uzupełniającymi. Aplikacja odpowiada także za szeregowanie publikacji na blogu, na przykład według miesiąca publikacji oraz kategorii – w celu łatwiejszego przeglądania. Dodatkowo mógłbyś ją rozszerzyć na przykład o wyszukiwarkę.
Istnieje możliwość dołączenia do projektu bloga kolejnych aplikacji, na przykład sondy internetowej. Taka sonda funkcjonalnie koncentruje się wokół magazynowania, przetwarzania i prezentacji pytań i udzielanych na nie odpowiedzi. Stanowi więc system nie będący w bezpośredniej zależności od bloga (opisując sprawę obrazowo, w dowolnym momencie masz możliwość „wyjęcia” sondy z bloga i wstawienia jej do innego projektu).
W praktyce pożądane jest niekiedy, aby aplikacje nie były idealnie niezależne. Bywa, że istnieje potrzeba by nieco się one zazębiały pomiędzy sobą – sonda może na przykład pobierać informacje o numerze ID notki na blogu, do której jest dołączona.
Ważne jednak, aby w takim przypadku taka integracja była jak najbardziej przejrzysta i skalowalna. Jeśli przeniesiesz sondę z bloga do systemu CMS, to powinna wystarczyć jedynie prosta podmiana ID notki na np. ID określonej wiadomości w aktualnościach na nowej stronie, żeby aplikacja ta zaczęła poprawnie funkcjonować.
Krok drugi: Stwórz aplikację bloga
1. Zdefiniuj modele danych
Prace nad blogiem rozpoczniemy od zdefiniowania modelu danych, czyli wzorca danych stosowanego w twojej aplikacji i zapisanego w bazie. Utworzymy model notki na blogu oraz jej przyporządkowania do kategorii. W tym celu w folderze aplikacji {stala}showblog{/stala} wyedytuj plik {stala}models.py{/stala} – służy on właśnie do opisywania modeli. Wprowadź modele zgodnie z ilustracją. Pamiętaj o tym, że Python bardzo rygorystycznie przestrzega zgodności wcięć w kodzie.
2. Dodaj aplikację do ustawień
Nie wystarczy jedynie utworzenie aplikacji w projekcie, by stała się ona aktywna. Należy jeszcze dodać ją do zainstalowanych aplikacji. W tym celu przejdź ponownie do pliku {stala}settings.py{/stala} i na jego końcu dopisz do {stala}INSTALLED_APS{/stala} pozycję {stala}blog.showblog{/stala}. Uzupełnij także listę {stala}TEMPLATE_CONTEXT_PROCESSORS{/stala} – co przyda się później.
3. Zsynchronizuj dane
Zanim omówimy stworzony model, przeprowadź jego synchronizację z bazą danych. Służy do tego specjalna operacja syncdb dostarczona wraz z narzędziami Django. Aby ją uruchomić, przejdź do katalogu głównego projektu i wydaj polecenie .{stala}/manage.py syncdb{/stala}. Przy pierwszym uruchomieniu tej opcji zostaniesz poproszony dodatkowo o podanie danych koniecznych do stworzenia konta administratora projektu.
4. Szczegóły modelu
W bazie utworzone zostały struktury danych, zgodne z opisem w modelu. Stworzony został model kategorii, który zawiera pole ID – klucz główny z autoinkrementacją oraz nazwę. Notki zawierają ID, tytuł, krótki opis (skrót), dłuższy opis, status widoczności oraz datę publikacji. Kategoria i autor są kluczami obcymi – pierwszy do stworzonego uprzednio modelu, drugi do modelu frameworka User (użytkownicy panelu administracyjnego).
5. Ustal wzorce adresu URL
Kolejnym krokiem jest precyzyjne ustawienie wzorców adresu. Musisz poinformować Django, że strona główna będzie dostępna w głównej ścieżce adresu URL, poszczególne notki na blogu będą mieć postać /{ID}/ (np. /36/), natomiast wzorzec dla listowania postów według miesiąca to /2008/03/. Wzorce mogą być dowolne, określasz je używając wyrażeń regularnych w pliku urls.py. Wpisz dane z ilustracji. Wzorcami dla listy kategorii zajmiemy się nieco później.
6. Użyj widoków generycznych
Szczegółowe objaśnienie zasady działania urls.py oraz widoków generycznych znajdziesz w artykule. Uzupełnij swój plik urls.py o definicję trzech słowników, przechowujących dane konfiguracyjne dla widoków generycznych – archive_info, index_info oraz note_info. Dodatkowo zaimportowaliśmy obiekt Note z aplikacji showblog. Dzięki gotowym do użycia widokom generycznym możesz dużo szybciej budować swoją aplikację.
7. Znajdź szablon dla bloga
Czas przystąpić do tworzenia szablonów bloga. W tym celu znajdź w internecie gotowe szablony HTML lub stwórz własny od podstaw. Tworząc przykładowego boga skorzystaliśmy z darmowego szablonu pochodzącego z serwisu http://www.freecsstemplates.org. Przed przystąpieniem do kolejnego kroku utwórz katalog {stala}templates{/stala} w głównej stronie projektu, a w nim katalog {stala}showblog{/stala} – tam wgrywać będziesz pliki HTML. Grafikę skopiuj do katalogu {stala}MEDIA_URL{/stala} ustawionego w {stala}settings.py{/stala}.
8. Przystosuj szablon strony głównej
Django oferuje dość uniwersalny system szablonów, do którego przekazywane są dane pochodzące z kontrolera. Można je przetwarzać za pomocą makroinstrukcji. Widoki generyczne przekazują dane o ustandaryzowanym nazewnictwie (np. object_list). Jeśli zwrócona została lista, wystarczy ją przejrzeć pętlą for i wstawić odpowiednie wartości – jak w przykładzie (plik zapisz jako index.html). Nagłówek oraz stopkę możesz wyłączyć do osobnych plików.
9. Przystosuj szablon notki
Czas na przygotowanie szablonu notki z bloga. Tym razem nie musisz stosować już pętli for – do szablonu przekazywane są dane konkretnej wiadomości na blogu. Są one widoczne pod postacią predefiniowanej nazwy object. Wystarczy, że w odpowiednich miejscach wstawisz znaczniki odwołujące się do poszczególnych pól modelu danych. Na koniec stwórz również szablon month.html (lista archiwum miesięcznego) oraz category.html (przyda się później). Mogą być one identyczne jak szablon index.html.
10. Przekaż własne dane do szablonu
Aby wyświetlić listę miesięcy będziesz musiał przekazać do szablonu własne dane. Jest to możliwe dzięki mechanizmowi „context processors”. W folderze aplikacji {stala}showblog{/stala} utwórz plik {stala}context_processor.py{/stala} z zawartością zgodną z ilustracją. Są to dwie metody zwracające potrzebne dane w postaci słownika. Metoda {stala}GetAllCategories(){/stala} przyda się później. Aby dostęp do wyniku był możliwy z poziomu szablonów, należy dołączyć funkcję procesora kontekstu do projektu poprzez {stala}settings.py{/stala} (co uczyniliśmy już w punkcie 2).
11. Stwórz szablon prawego menu
Do strony głównej dołączony został (include) szablon side.html. Przygotuj go zgodnie ze wzorcem z ilustracji. Wykorzystywane są tutaj globalne wartości przekazane przez „context processor” – listy, które możesz przeglądać i wyświetlać korzystając z instrukcji for. Zastosowane została również użyta jedna funkcja formutująca, dostępna spośród licznych zaimplementowanych w mechaniźmie Django – date.
12. Aplikacja już działa
Gratulacje, twoja aplikacja posiada już pewną funkcjonalność. Po dodaniu przykładowych informacji za pośrednictwem panelu administracyjnego, blog będzie wyglądać tak jak na ilustracji.
Django natywnie używa kodowania UTF8. Choć możesz chcieć używać kodowania ISO-8859-2, lepiej twórz swoje strony już w oparciu o Unicode. Będziesz do tego potrzebował edytora, który potrafi zapisywać dokumenty w tym kodowaniu lub odpowiedniego konwertera.
Krok trzeci: Wyczaruj panel administracyjny
1. Dodaj ściężkę URL dla panelu
Django potrafi automatycznie wygenerować panel administracyjny do tworzonej treści.
Zaraz sam przekonasz się, w jak prosty sposób się to odbywa. Zacznijmy od zaprojektowania ścieżki adresu URL dla panelu. Zakładamy, że panel będzie dostępny po wpisaniu ścieżki {stala}/admin/{/stala}. Poddaj edycji plik urls.py i wprowadź w nim jedną krótką linię.
2. Dodaj panel do aplikacji
Aby panel administracyjny mógł zostać obsłużony przez Django, należy go dodać do zainstalowanych aplikacji w projekcie. W tym celu przejdź do pliku settings.py, a następnie do listy {stala}INSTALLED_APPS{/stala} dopisz wartość {stala}django.contrib.admin{/stala}. Po tej operacji konieczna będzie synchronizacja projektu z bazą danych. W tym celu wydaj polecenie {stala}./manage.py syncdb{/stala}. Pamiętaj, aby synchronizować bazę po każdym dodaniu aplikacji.
3. Zaloguj się do panelu
Wpisz w przeglądarce adres http://www.twojastrona.pl/admin/. Powinien wyświetlić się ekran logowania. Jeśli nie widzisz obrazów i stylów, oznacza to, że na serwerze HTTP nie został stworzony właściwy alias do katalogu z zawartością statyczną panelu. Poproś o pomoc administratora swojego serwera. Zaloguj się do panelu, używając swojego loginu oraz hasła wybranego w czasie pierwszej synchronizacji bazy danych.
4. Uruchom dostęp do modelu danych
Aktualnie w panelu administracyjnym masz jedynie możliwość zarządzania jedynie użytkownikami. Dane aplikacji showblog nie są jeszcze dostępne. Aby to zmienić należy wskazać Django, że chcesz uruchomić zarządzanie danymi przez panel. Przejdź do {stala}models.py{/stala} aplikacji {stala}showblog{/stala} i wprowadź w definicji modelu klasę Admin, zgodnie z ilustracją. Słowo kluczowe {stala}pass{/stala} informuje Pythona, że klasa jest pusta.
5. Dostrój widoku modelu
W tej chwili możesz już zarządzać modelem poprzez panel. Warto jednak dostroić domyślne ustawienia. Uzupełnij {stala}models.py{/stala} zgodnie z powyższą ilustracją, aby wprowadzić kilka zmian. Dzięki nim określisz sposób wyświetlania nazw modeli ({stala}verbose_name{/stala}), a także wyświetlanie samego modelu w kontekście skalarnym (istotne przy listowaniu). Dokonasz nawet przeciążenia metody {stala}save{/stala}, aby automatycznie uzupełnić pole daty w nowym wpisie.
6. Zacznij korzystać z panelu
Możesz już wykorzystać panel administracyjny do dodania pierwszych informacji na swojego bloga. Na początek wprowadź dostępne kategorie notek, gdyż będziesz do nich linkować z edycji wpisu (notki). W samym wpisie masz dostępnych kilka wartości. Pola daty nie musisz wypełniać – zostanie ono uzupełnione automatycznie. Dodawane artykuły powinny natychmiast pojawić się na twoim blogu.
Konfiguracja projektu
Wiesz już, w jaki sposób zorganizowany jest projekt. Warto jeszcze poświęcić chwilę przygotowaniu projektu do pracy. Po jego utworzeniu musisz przede wszystkim skonfigurować środowisko za pomocą pliku settings.py. Przykład praktyczny zamieściliśmy na końcu artykułu – krok po kroku tworzymy projekt nowego bloga. W tym miejscu należy jedynie zwrócić uwagę na kilka ustawień, które pominięte zostały w przykładzie praktycznym.
Django potrafi pracować w trybie z włączonym debbugerem. Tryb taki powoduje precyzyjne wyświetlanie informacji o błędach oraz ich źródle w przeglądarce użytkownika. Jest to bardzo przydatne podczas tworzenia aplikacji, ale bezwzględnie powinieneś go wyłączyć po zakończeniu prac nad projektem. Tryb ten może bowiem sprawić, że potencjalni napastnicy dowiedzą się o twojej aplikacji więcej niż powinni. Ponadto zmniejsza on wydajność aplikacji.
Warto również pamiętać, że jeśli uruchamiasz kilka projektów, należy im ustawić odrębne wartości SITE_ID. Ustrzeże cię to przed problemem konfliktu plików cookie z poszczególnych projektów w tej samej domenie. Zaraz po stworzeniu nowego projektu, dołączanych jest do niego kilka standardowo zainstalowanych aplikacji oraz middletów dostarczonych wraz z Django, a wykorzystywanych m.in. w panelu administracyjnym do autoryzacji użytkowników. Mogą ci się one przydać także w tworzonym przez siebie kodzie.
Ciekawym plikiem jest urls.py – umożliwia on sterowanie adresami internetowymi wykorzystywanymi w projekcie. Django przechwytuje wszystkie wywołania URL, zaś plik urls.py służy do ich dopasowania wedle określonych wzorców do określonych aplikacji i zachowań. Funkcjonalnie jest to więc odpowiednik routes.rb z RoR, choć sposób działania urls.py jest inny.
Projektowanie adresów URL odbywa się za pomocą wyrażeń regularnych wraz z podaniem nazwy aplikacji, do której zostanie przekazane zapytanie jeśli wzorzec zostanie dopasowany pomyślnie. Przeanalizujmy następujący przykład:
urlpatterns = patterns('',
# Test
(r'^test/', 'projekt.aplikacja.views.test'),
# Test2
(r'^test2/(.*)', 'projekt.aplikacja.views.test2'),
# Panel administratora
(r'^admin/', include('django.contrib.admin.urls'))
)
Jeśli adres URL rozpoczyna się od {stala}test/{/stala} (w stosunku do względnej ścieżki URL projektu) to zapytanie zostanie przekazane do funkcji test, zdefiniowanej w pliku widoków {stala}views.py{/stala} w ramach aplikacji o nazwie {stala}aplikacja{/stala}, w projekcie o nazwie {stala}projekt{/stala}. W dalszej części artykułu, analizując widoki dowiesz się, w jaki sposób możesz obsłużyć takie zapytanie.
Do widoku przekazywane są również informacje dynamiczne pochodzące z adresu URL. Spójrz na drugi przykład, który przekazuje zapytanie do funkcji {stala}test2{/stala}. W widoku tym będziesz miał możliwość „odebrania” informacji zawartej w nawiasie okrągłym (zgodnie z regułami regexp kropka i gwiazdka oznacza dowolny ciąg znaków). A więc twoja metoda może dostosować swoje zachowanie do otrzymanego parametru.
Wreszcie trzeci przykład pokazuje, w jaki sposób można uzyskać dostęp do panelu administracyjnego (dostarczonego wraz z Django). A także, jak skorzystać z możliwości dołączenia pliku definicji URL. Przy bardziej rozbudowanych aplikacjach dobrze jest utworzyć w ramach aplikacji odrębne pliki urls.py – zwiększa to przejrzystość tego rozwiązania oraz jego skalowalność.
Istnieje ponadto możliwość przekazywania dodatkowych opcji do funkcji poprzez trzeci element listy zdefiniowanej w {stala}urlpatterns{/stala}. Praktyczne zastosowanie poznasz w trakcie tworzenia przykładowego bloga zgodnie z naszymi instrukcjami.
Model danych
Plik definiujący modele danych znajduje się w folderze aplikacji i nosi nazwę {stala}models.py{/stala}. Wewnątrz niego możesz tworzyć klasy odpowiadające poszczególnym modelom. Rodzi się pytanie – czym jest model? Trudno o krótką definicję. Z jednej strony jest to określona, jednolita struktura danych opisująca stan obiektu wraz z jego atrybutami. Przenosząc to na terminologię programowania obiektowego – model jest obiektem, zawierającym atrybuty, ale nie zawierającym metod. Z kolei przekładając model wprost na implementację w strukturach bazodanowych, jest to pojedyncza tabela relacyjnej bazy danych.
Bardzo wygodną cechą Django jest jego wysokopoziomowa obsługa pól w modelu. Dostępne typy danych nie ograniczają się wyłącznie do kilku podstawowych (np. łańcuch, liczba czy data), ale obsługują znacznie więcej typów abstrakcyjnych. Są one na dodatek wygodnie przedstawiane w panelu administracyjnym – na przykład typ daty zostanie uzupełniony o kalendarz, z którego możesz wybrać interesującą cię datę.
Oto przykładowy model, wyjęty z naszej aplikacji blogowej:
from django.db import models
from datetime import datetime
from django.contrib.auth.models import User
class Category(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField("Kategoria", maxlength=100)
class Note(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField("Tytuł", maxlength=150)
description = models.TextField("Krótki opis")
text = models.TextField("Treść")
visible = models.BooleanField("Widoczny", default=True)
publish_date = models.DateTimeField("Data publikacji", blank=True, editable=False)
author = models.ForeignKey(User, verbose_name="Autor")
categories = models.ManyToManyField(Category, verbose_name="Kategorie")
Model tworzysz poprzez dodanie odpowiadającej mu klasy (dziedziczącej po models.Model), a następnie poprzez utworzenie atrybutów. Są one obiektami odpowiednich typów danych. W powyższym przykładzie zawarto na przykład obiekty klasy CharField, TextField, BooleanField czy DateTimeFiled.
Są to określone wysokopoziomowe typy, które niezależnie od standardowych typów dostarczanych przez Pythona posiadają zaimplementowany określony rodzaj zachowań oraz przyjmują typowe dla siebie wartości (Django będzie sprawdzać, czy przekazane dane są poprawne). W panelu administracyjnym każdy z takich typów symbolizowany jest w inny sposób. O ile CharField jest jednoliniowym polem tekstowym to TextField stanowi pole wielowierszowe ({html}
Dostępnych jest także wiele innych rodzajów pól, z których możesz korzystać w swoich modelach. Dla przykładu pole typu PositiveIntegerField pozwala wprowadzać tylko liczby dodatnie, URLField oczekuje adresu URL, a {stala}FileField{/stala} umożliwi wskazywanie plików. Warto również dodać, że choć w standardzie brakuje w Django typu reprezentowanego w panelu administracyjnym przez edytor WYSIWYG, to w internecie nie brakuje instrukcji pokazujących, w jaki sposób można dokonać modyfikacji i mieć do dyspozycji ten wygodny dodatek.
Istnieje także pewna grupa typów specjalnych, wśród nich trzy zastosowane w powyższym modelu:
- AutoField – jest typem liczbowym, który posiada zdolność autoinkrementacji. Z tego względu wykorzystywany jest jako klucz podstawowy modeli (najlepiej, gdy klucz taki posiada zawsze nazwę {stala}id{/stala}).
- ForeignKey – jest odpowiednikiem klucza obcego w modelu relacyjnym. Pozwala wskazywać powiązany model podrzędny (powiązanie typu „wiele do jednego”).
- ManyToManyField – również pozwala powiązać ze sobą modele, ale tym razem dozwolonych jest wskazanie kilku z nich.
- Pełną listę dostępnych typów danych, które możesz wykorzystać w swoich modelach znajdziesz w dokumentacji Django.
- Konstruktor każdego z typów może przyjmować dodatkowe parametry. Ich lista również jest szczegółowo przedstawiona w dokumentacji. Najważniejsze parametry precyzują m.in. sposób wyświetlania danych w panelu (opis) oraz maksymalną dopuszczalną długość pola tekstowego.
Widok
Jak już wspomnieliśmy, widok w Django jest miejscem gdzie zdefiniowana została logika biznesowa (jest to kontroler w klasycznej terminologii MVC). Widoki tworzysz poprzez utworzenie funkcji w {stala}views.py{/stala}, a następnie wskazanie jej nazwy w {stala}urls.py{/stala}.
Oto przykład prostego widoku:
def index(request):
return HttpResponse('Strona główna
')
def test(request):
return HttpResponse('Podstrona test/
')
Następnie dodaj odpowiednie wpisy w url.py:
urlpatterns = patterns('',
(r'^/', 'blog.showblog.views.index'),
(r'^/test/', 'blog.showblog.views.test')
)
Wszystkie wywołania ze strony głównej projektu będą przekazywane do funkcji index, z kolei wywołania adresu /test/ do funkcji {stala}test(){/stala}. Obie funkcje są bardzo proste – zwracają gotową odpowiedź ze stroną HTML dla serwera WWW.
Do swoich funkcji możesz także przekazywać bezpośrednio parametry z adresu URL. Oto kolejna funkcja widoku:
def test2(request, nr):
return HttpResponse('Podstrona test/(%s)/
' % nr)
Uzupełnij definicje dla parsera URL:
urlpatterns = patterns('',
(r'^/', 'blog.showblog.views.index'),
(r'^/test/', 'blog.showblog.views.test'),
(r'^/test/([0-9]+)', 'blog.showblog.views.test'
)
Do funkcji {stala}test2(){/stala} zostaną przekazane parametry występujące we wzorcu wyrażeń regularnych w nawiasach okrągłych, w kolejności ich występowania. Zostało to wykorzystane w naszym przykładzie do wyświetlenia odpowiedniej informacji w przeglądarce użytkownika.
Możesz także przekazywać parametry w sposób nazwany:
urlpatterns = patterns('',
(r'^/', 'blog.showblog.views.index'),
(r'^/test/', 'blog.showblog.views.test'),
(r'^/test/(?P[0-9]+)', 'blog.showblog.views.test'
)
W takim przypadku kolejność wystąpień parametru w adresie URL nie musi być zgodna z kolejnością parametrów przyjmowanych przez funkcję widoku.
W samym widoku możesz również niezależnie parsować parametry otrzymane metodą POST oraz GET – tę oraz wiele innych funkcjonalności otrzymujesz wraz z obiektem request przekazywanym do funkcji.
Prezentację sposobu obsługi parametrów POST (otrzymanych z formularzy) znajdziesz w przykładzie praktycznym uzupełniającym artykuł. Po szczegóły odsyłamy do dokumentacji frameworka.
Widoki generyczne
Django ułatwia pracę związaną z najczęściej spotykanymi rodzajami zachowań, poprzez dostarczenie pewnej grupy widoków generycznych. Są to predefiniowane widoki, które możesz wykorzystywać w swoich aplikacjach, bez potrzeby pisania ich od początku. Jeśli korzystasz z pewnej grupy standardowej funkcjonalności to widoki generyczne będą dla ciebie świetnym rozwiązaniem.
Przykłady dostępnych widoków generycznych:
- django.views.generic.simple.redirect_to – szybkie przekierowanie do określonej strony
- django.views.generic.date_based.archive_year – wyświetlanie listy dokumentów (modeli) według rocznika (dostępne także podziały miesięczne, tygodniowe, dzienne i inne)
- django.views.generic.list_detail.object_list – wyświetla listę dokumentów według dowolnego innego kryterium (możesz filtrować listę dokumentów poprzez przekazanie odpowiedniego obiektu do obowiązkowego parametru {stala}queryset{/stala}).
- django.views.generic.list_detail.object_detail – wyświetla zawartość dokumentu (modelu) o określonym {stala}object_id{/stala} lub {stala}slug_name{/stala} (ten ostatni to specjalny ciąg znaków, którego można używać w URL do identyfikowania konkretnego dokumentu).
- django.views.generic.create_update.create_object – pozwala w łatwy sposób rozszerzać istniejące modele.
Dostępnych jest jeszcze kilka innych wariantów. Korzystanie z tego rodzaju ułatwień jest bardzo proste – wystarczy, że wskażesz je w pliku urls.py zamiast widoku swojej aplikacji. Możesz również przekazać słownik z dodatkowymi ustawieniami (przy niektórych z nich będzie to konieczne, jak w przypadku {stala}queryset{/stala} dla widoku {stala}object_list{/stala}).
Szablony
Gdy stworzyłeś już model danych, zadbałeś o opracowanie logiki biznesowej i dołączenie jej do projektu, czas zająć się warstwą prezentacji. W Django, jak i w wielu innych frameworkach zadanie to jest realizowane poprzez system szablonów. Jeśli pracowałeś już z systemami szablonów w innych językach programowania (np. Smarty w PHP) to opanowanie funkcjonalności dostarczanej przez Django nie powinno stanowić dla ciebie większego problemu.
Oto jak wygląda fragment szablonu:
Archiwum
-
{% for month in months %}
- {{ month|date:"F Y" }} {% endfor %}
Pętla for przegląda pozycję po pozycji kolejne elementy listy months, które w jej wnętrzu dostępne są pod wartością month. Należy zwrócić tutaj uwagę na fakt, że jest to działanie pętli for w stylu Pythona. Jej odpowiednikiem w PHP byłaby pętla foreach. System szablonów Django dostarcza także cały szereg instrukcji dostępnych z poziomu szablonów – zapisywane są one w kodzie z użyciem nawiasów klamrowych oraz znaku procenta.
Wartości wstawiane są do szablonu przy użyciu tagu składającego się z podwójnych nawiasów klamrowych. Dodatkowo po pionowej kresce można wstawić instrukcje formatujące. Użyta funkcja date służy do sformatowania sposobu wyświetlania daty w kodzie wynikowym (zakładając, że month zawiera typ datetime).
Dostępnych jest wiele innych instrukcji formatujących. Z ciekawszych można wymienić na przykład „slugify”, który jest przydatny do tworzenia przyjaznych adresów URL – zamienia np. tytuł dokumentu na postać, która można wstawić wprost do adresu URL. Niestety, domyślnie funkcjonalność „slugify” w Django nie radzi sobie z polskimi znakami. W internecie istnieją jednak modyfikacje Django pozwalające to zmienić.
W jaki sposób odwoływać się do szablonów z postaci własnych widoków? Oto przykład:
from django.shortcuts import render_to_response
def person_info(request):
person = { 'imie': 'Jan', 'nazwisko': 'Kowalski', 'miejscowosc': 'Warszawa' }
return render_to_response('person/person_info.html', person)
Wykorzystywany jest tzw. skrót – specjalna metoda wchodząca w skład mechanizmów Django, dzięki której określone operacje realizuje się szybciej. Skrót {stala}render_to_responce{/stala} pozwala jednym poleceniem wygenerować stronę wynikową, przekazując adres szablonu oraz słownik z przekazywanymi danymi. Wewnątrz szablonu można się do nich odwoływać poprzez odpowiadające tym danym tagi {stala}{{ imie }}, {{ nazwisko }}, {{ miejscowosc }}{/stala}.
Do szablonów można przekazywać także słowniki z danymi zdefiniowanymi globalnie. Służy do tego mechanizm „text processors”, który wykorzystywany jest w praktycznym uzupełnieniu artykułu. Można pójść jeszcze krok dalej – Django pozwala tworzyć całkowicie niezależne tagi, instrukcje oraz funkcje formatujące. Możliwości dostosowania mechanizmu szablonów do własnych potrzeb są bardzo szerokie.
Na zakończenie
W dużym skrócie staraliśmy się zaprezentować możliwości jakie oferuje Django. Ma on swoje zalety i wady. Sympatyków RoR może być trudno przekonać, że jest to rozwiązanie lepsze. Wydaje się jednak, że warto poznać Django, bowiem może on znaleźć zastosowanie w wielu projektach. A nierzadko może okazać się nawet, że Django jest frameworkiem pozwalającym pisać pewne rzeczy znacznie szybciej.
Django wyróżnia się automatycznie generowanym panelem administracyjnym – temat ten powracał przez cały artykuł. To rzeczywiście bardzo wygodna sprawa – po stworzeniu aplikacji od strony internauty nie trzeba już poświęcać czasu na tworzenie części dla administracji. Należy jednak mieć świadomość, że możliwości dostarczonego przez twórców Django panelu są ograniczone. Ma on swój określony styl i nie będzie łatwo wprowadzić w nim rewolucyjnych zmian.
Aby nieco naświetlić przedstawioną w artykule wiedzę teoretyczną, na kolejnych stronach prezentujemy przykład stworzenia krok po kroku prostej aplikacji blogowej. Dzięki niemu przekonasz się, że stworzenie projektu w Django nie zajmuje wiele czasu. Zobaczysz również, jak przebiegają prace.
Przykład zrealizowany został w oparciu o Django w wersji 0.96 – jest to ostatnia stabilna wersja frameworka dostępna w chwili przygotowania artykułu. Wkrótce powinna pojawić się nowa wersja, oznaczona jako 2.0 (twórcy zrezygnowali z pośredniej wersji 1.0).
Jeśli zainteresował cię temat Django – zapraszamy na strony internetowe poświęcone temu zagadnieniu. Polskie grono sympatyków Django dopiero się tworzy. Masz zatem szansę współtworzyć podwaliny równie aktywnej społeczności, jak chociażby środowisko zorganizowane wokół Ruby On Rails.
Gdzie szukać hostingu dla Django
W Polsce nie ma zbyt wielu firm hostingowych oferujących konta dla programistów Django. Najciekawszą ofertę wydaje się prezentować MegiTeam (http://www.megiteam.pl). Serwery tej firmy obsługują także inne frameworki Pythona oraz Ruby On Rails.
Inna alternatywa to skorzystanie z platform wirtualnych firmy KEI (http://www.kei.pl), gdzie na życzenie istnieje możliwość uruchomienia Django (usługi te są jednak nieco droższe) lub z oferty firmy Insane (http://www.insane.pl).
Krok pierwszy: Przygotowanie projektu
1. Utwórz nowy projekt
Zaloguj się do linii poleceń (shell) serwera. Przejdź do głównego katalogu – tego, który jest ustawiony w ścieżce PYTHON_PATH. Najczęściej jest to twój katalog domowy lub public_html. Jeśli masz wątpliwości, zapytaj swojego administratora. Następnie wydaj dwa polecenia: {stala}django-admin.py startproject blog {/stala}. Wejdź do katalogu i wydaj polecenie {stala}django-admin.py startapp showblog {/stala}.
2. Zapoznaj się ze strukturą projektu
Polecenie „startproject” utworzyło nowy projekt – w systemie widoczny jako katalog, o nazwie zgodnej z nazwą projektu, z kilkoma prekonfigurowanymi plikami. Nasz przykładowy projekt nosi nazwę „blog”. Aplikację nazwaliśmy „showblog” (nie może ona być taka sama jak nazwa projektu). Pamiętaj, że w ramach jednego projektu możesz tworzyć wiele aplikacji. Różnice między projektem a aplikacją opisaliśmy w artykule.
3. Konfiguracja dostępu do bazy danych
W katalogu projektu otwórz do edycji plik settings.py. To tu wprowadza się podstawową konfigurację projektu. W górnej części należy podać dane dostępowe do bazy – zapisz informacje o swojej bazie, zgodnie z wytycznymi dostawcy hostingu. Możesz wybrać rodzaj bazy danych spośród kilku obsługiwanych: SQLite (najprostsza, oparta wprost na plikach), MySQL, PostgreSQL oraz Microsoft SQL.
4. Doprecyzuj pozostałe ustawienia
Poświęć kilka chwil na dogranie pozostałych ustawień. Zmień strefę czasową i język, a jeśli masz więcej projektów Django – nadaj każdemu inny ID. Ustaw ścieżkę dostępu do plików statycznych, zarówno systemową (MEDIA_ROOT), jak i ścieżkę wywołania URL (MEDIA_URL). Ścieżkę dla panelu administracyjnego pozostaw domyślną, a gdyby okazała się błędna – uzgodnij to z administratorem (wymaga ona aliasu na poziomie serwera HTTP).
5. Ustaw domenę do obsługi projektu
Do pozostałych ustawień z settings.py jeszcze wrócimy. Aby móc korzystać ze swojej strony, musisz jeszcze skonfigurować domenę do jej obsługi. Najczęściej wymaga to skorzystania z panelu administracyjnego lub kontaktu bezpośrednio z administratorami. Należy skierować domenę na określony katalog oraz dodatkowo ustawić kilka rzeczy w konfiguracji serwera WWW – to już jednak zadanie dla firmy hostingowej.
6. Twój projekt już działa
Możesz już odwiedzić stronę swojego projektu. Wprowadzone ustawienia wystarczają, aby móc poprawnie uruchomić Django. Można powiedzieć, że właśnie stworzyłeś pierwszą aplikację Django. W kolejnych krokach postaramy się, aby była ona nieco bardziej funkcjonalna.
Zapytaj swojego dostawcę hostingu, czy istnieje możliwość obsługi katalogu z plikami statycznymi bezpośrednio przez serwer statyczny. Znacznie przyspieszy to działanie serwisu.
Krok czwarty: Wstaw listę kategorii i komentarze
1. Dostosuj konfigurację URL
W poprzednich krokach wykorzystaliśmy widoki generyczne do szybkiego tworzenia aplikacji. Część zmian wymagać jednak będzie zastosowania własnych widoków – wprowadzimy listę kategorii oraz możliwość komentowania. Rozpocznij od dostosowania {stala}urls.py{/stala} do przyjmowania odpowiednich wzorców adresów URL. Wprowadź zmiany zgodnie z ilustracją – dla przeglądu notek w kategorii oraz obsługi komentarzy.
2. Dodaj funkcję widoku
W pliku {stala}urls.py{/stala}, w przypadku dopasowania adresu URL do wprowadzonych wzorców, wywołane będą już nie widoki generyczne, a te samodzielnie napisane. Wstaw widok do pliku views.py w katalogu aplikacji {stala}showblog{/stala}, aby dodać funkcję obsługi listy komentarzy. Jednak widok generyczny nie pozwala filtrować danych w oczekiwany sposób. Dodając trzy linie kodu możesz rozszerzyć go o własną funkcjonalność.
3. Rozszerz szablon side.html
Jak działa funkcja z poprzedniego kroku? Przyjmuje ona takie same argumenty, jak funkcja generyczna. Wystarczy, że rozszerzysz obiekt queryset przetwarzający dane o własny dodatkowy filtr i wywołasz właściwą funkcję generyczną. Aby internauta mógł dostać się do listowania kategorii, w pliku side.html wyświetl listowanie z procesora kontekstu.
4. Dodaj model komentarza
Przejdźmy do tworzenia komentarzy. Na wstępie musisz stworzyć odpowiedni model, który będzie zawierać kilka pól z danymi właściwymi dla komentarza, wraz z kluczem obcym wiążącym komentarz z postem, do którego został wystawiony. Jak już się pewnie domyślasz, zmian dokonujesz w pliku {stala}models.py{/stala}. Po ich wprowadzeniu zsynchronizuj bazę danych, korzystając z polecenia {stala}./manage.py syncdb{/stala}.
5. Dodaj widok dla komentarzy
Zrób użytek ze stworzonego modelu. Plik urls.py jest już skonfigurowany, musisz więc jedynie dodać odpowiednie funkcje widoku dla obsługi komentarzy. Będziesz potrzebował ich dwóch. Pierwsza rozszerzy obsługę posta na blogu o wyświetlanie jego komentarzy, z kolei druga dostarczy możliwości ich dodawania na podstawie analizy parametru POST otrzymanego z formularza.
6. Rozszerz szablon note.html
Pozostało już tylko rozszerzyć szablonu widoku notki o nową funkcjonalność. Musisz wstawić formularz HTML umożliwiający wysłanie komentarza, jak również wprowadzić pętlę pozwalającą przeglądać dostępne dla notki formularze (dostarczane do szablonu przez stworzony przed chwilą widok {stala}note_details{/stala}). I to wszystko! Od teraz komentarze są już dostępne na twoim blogu, choć możesz pokusić się o samodzielne rozszerzenie ich o mechanizmy antyspamowe oraz obsługę błędów.
Definiując parametry w dwóch funkcjach widoku zastosowaliśmy zapis *args oraz **kwargs. To wygodny sposób w Pythonie na przekazywanie parametrów przez listę i słownik. Przydaje się szczególnie tam, gdzie lista parametrów nie jest bliżej znana lub może być zmienna.