Django w pigułce

PoniewaŜ Django powstawało w środowisku dziennikarskim, gdzie szybkość ma niebywałe znaczenie, zostało tak zaprojektowane, by móc szybko i łatwo wykonywać typowe zadania związane z tworzeniem stron internetowych. Oto krótki i nieformalny opis tego, jak napisać w Django aplikację wykorzystującą bazę danych do przechowywania informacji. Celem tego dokumentu jest przedstawienie wystarczającego opisu technicznego, by zrozumieć, jak działa Django, ale nie jest to ćwiczenie ani opis poszczególnych funkcji. Zajrzyj do naszej szczegółowej dokumentacji Django, jeśli stwierdzisz, Ŝe chcesz zacząć nowy projekt.

Zaprojektuj swój model
Choć moŜna uŜywać Django bez bazy danych, dostarczamy je wraz z systemem ORM (odwzorowanie relacyjno-obiektowe). Za pomocą ORM moŜesz zdefiniować tabele w bazie danych oraz pracować na nich — pisząc i operując na klasach w Pythonie. Składnia danych modelu zapewnia wiele róŜnorodnych sposobów przedstawiania modeli — jak do tej pory udawało jej się przez dwa lata rozwiązywać problemy ze schematem bazy danych. Oto krótki przykład:
class Reporter(models.Model): full_name = models.CharField(max_length=70) def __unicode__(self): return self.full_name class Article(models.Model): pub_date = models.DateTimeField() headline = models.CharField(max_length=200) article = models.TextField() reporter = models.ForeignKey(Reporter) def __unicode__(self): return self.headline

Instalacja modelu
Skorzystaj z narzędzia administracyjnego z wiersza poleceń, by automatycznie utworzyć tabele bazy danych:
manage.py syncdb

Polecenie syncdb analizuje wszystkie dostępne modele i tworzy te tabele bazy danych, które jeszcze w niej nie istnieją.

Skorzystaj z dostępnego API

1

Za darmo otrzymujesz bogaty interfejs programistyczny w Pythonie zapewniający dostęp do danych. API powstaje w locie, nie jest potrzebna Ŝadna generacja kodu:
>>> from mysite.models import Reporter, Article # W systemie nie ma jeszcze Ŝadnych reporterów. >>> Reporter.objects.all() [] # Utwórz nowego reportera (obiekt klasy Reporter). >>> r = Reporter(full_name='Jan Kowalski') # Zapisz obiekt w bazie danych. Musisz jawnie wywołać metodę save(). >>> r.save() # Teraz obiekt ma nadany identyfikator. >>> r.id 1 # Reporter znajduje się w bazie danych. >>> Reporter.objects.all() [Jan Kowalski] # Pola bazy są atrybutami Pythonowego obiektu. >>> r.full_name 'Jan Kowalski' # Django udostępnia bogaty interfejs do wyszukiwania danych. >>> Reporter.objects.get(id=1) Jan Kowalski >>> Reporter.objects.get(full_name__startswith='Jan') Jan Kowalski >>> Reporter.objects.get(full_name__contains='walsk') Jan Kowalski >>> Reporter.objects.get(id=2) Traceback (most recent call last): ... DoesNotExist: Reporter does not exist for {'id__exact': 2} # Utwórz artykuł. >>> from datetime import datetime >>> a = Article(pub_date=datetime.now(), headline='Django jest super', ... article='Racja.', reporter=r) >>> a.save() # Teraz artykuł znajduje się w bazie danych. >>> Article.objects.all() [Django jest super] # Obiekt artykułu umoŜliwia łatwy dostęp do powiązanego z nim obiektu reportera. >>> r = a.reporter >>> r.full_name 'Jan Kowalski' # I odwrotnie: # Obiekt reportera umoŜliwia łatwy dostęp do powiązanych z nim artykułów. >>> r.article_set.all() [Django jest super] # Interfejs automatycznie wykorzystuje związki tak daleko, jak to będzie

2

# potrzebne, stosując złączenia bazodanowe (Django doda je automatycznie). # Przedstawiony przykład znajduje wszystkie artykuły reportera, którego imię # zaczyna się na "Jan". >>> Article.objects.filter(reporter__full_name__startswith="Jan") [Django jest super] # Zmień obiekt, modyfikując jego atrybuty i wywołując metodę save(). >>> r.full_name = 'Piotr Nowak' >>> r.save() # Usuń obiekt metodą delete(). >>> r.delete()

Interfejs administracyjny: to nie tylko fundamenty — to cały dom
Po zdefiniowaniu modeli, Django potrafi automatycznie stworzyć profesjonalny, gotowy do wykorzystania w produkcji interfejs administracyjny — witrynę, która umoŜliwia uwierzytelnionym osobom dodawać, edytować i usuwać obiekty. Aby włączyć interfejs, wystarczy dodać do kodu modelu jeden dodatkowy wiersz:
class Article(models.Model): pub_date = models.DateTimeField() headline = models.CharField(max_length=200) article = models.TextField() reporter = models.ForeignKey(Reporter) class Admin: pass

Filozofia jest następująca — Ty, Twój klient lub zespół redakcyjny edytujecie dane witryny. Nie chcesz więc poświęcać czasu na tworzenie osobnych interfejsów administracyjnych tylko do zarządzania zawartością. W Django bardzo często zdarza się, Ŝe modele powstają bardzo szybko wraz z włączonym systemem administracyjnym, by zespół redakcyjny (lub klienci) mogli zacząć wypełniać dane. Programiści i projektanci mogą się w tym czasie zająć utworzeniem publicznie dostępnej części interfejsu.

Zaprojektuj adresy URL
Czysty, elegancki wygląd adresów URL to bardzo waŜny szczegół w wysokiej jakości aplikacjach WWW. Django zachęca do stosowania ładnych adresów URL, które nie kończą się brzydkimi rozszerzeniami typu .php lub .asp. Aby zaprojektować adresy URL dla aplikacji, tworzymy moduł Pythona nazywany URLconf. Stanowi on niejako spis zawartości aplikacji, zapewniają proste odwzorowanie między wzorcami URL i funkcjami Pythona. URLconf zapewnia równieŜ bardzo dobre oddzielenie adresów URL od głównej logiki aplikacji. PoniŜej znajduje się przykładowy plik URLconf dla przedstawionego wcześniej przykładu z Reporter i Article:

3

from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^artykuly/(\d{4})/$', 'mysite.views.year_archive'), (r'^artykuly/(\d{4})/(\d{2})/$', 'mysite.views.month_archive'), (r'^artykuly/(\d{4})/(\d{2})/(\d+)/$', 'mysite.views.article_detail'), )

Odwzorowanie polega na znalezieniu pasującego wyraŜenia regularnego, a następnie wywołanie odpowiadającej mu funkcji widoku (ang. view). WyraŜenia regularne stosują nawiasy do “wyłapania” wartości z adresów URL. Gdy uŜytkownik wysyła Ŝądanie pobrania strony, Django przechodzi po kolei przez kaŜdy z wzorców i zatrzymuje się na pierwszym, który odpowiada Ŝądanemu adresowi URL. (Jeśli dopasowania nie uda się znaleźć, Django wywołuje specjalny widok dla błędu 404). Rozwiązanie to jest wyjątkowo szybkie, poniewaŜ Django kompiluje wyraŜenia regularne w trakcie uruchamiania aplikacji serwerowej. Gdy Django znajdzie pasujące wyraŜenie regularne, importuje i wywołuje wskazany widok, który jest zwykłą Pythonową funkcją. Do kaŜdego widoku trafia obiekt Ŝądania — zawierający metadane Ŝądania — oraz wartości zebrane podczas analizy wyraŜenia regularnego. Jeśli na przykład uŜytkownik zaŜąda adresu URL “/artykuly/2005/05/39323/”, Django wywoła funkcję mysite.views.article_detail(request, '2005', '05', '39323').

Napisz widoki
KaŜdy widok odpowiada za wykonanie jednej z dwóch rzeczy: zwrócenie obiektu HttpResponse zawierającego zawartość Ŝądanej strony lub zgłoszenie wyjątku takiego jak Http404. To, co się będzie działo w jego wnętrzu, zaleŜy od Ciebie. Ogólnie rzecz biorąc widok pobiera dane zgodnie z przekazanymi parametrami, wczytuje szablon i renderuje go, wykorzystując pobrane dane. Oto przykład widoku year_archive dla wcześniejszego przykładu z adresami URL:
def year_archive(request, year): a_list = Article.objects.filter(pub_date__year=year) return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list} )

Przykład wykorzystuje system szablonów Django, który ma kilka potęŜnych funkcji, ale jednocześnie pozostaje na tyle prosty, by mógł być wykorzystywany przez osoby niezaznajomione z programowaniem.

Zaprojektuj szablony
Przedstawiony powyŜej kod wczytuje szablon news/year_archive.html. Django wykorzystuje ścieŜkę wyszukiwania szablonów, która umoŜliwia minimalizację redundancji między szablonami. W pliku ustawień określa się listę folderów, które naleŜy

4

sprawdzić w poszukiwaniu szablonów. Jeśli szablon nie istnieje w pierwszym folderze, sprawdza następny itd. Przypuśćmy, Ŝe znaleziono szablon o nazwie news/article_detail.html. Oto jak mógłby on wyglądać:
{% extends "base.html" %} {% block title %}Artykuły z roku {{ year }}{% endblock %} {% block content %} <h1>Artykuły z roku {{ year }}</h1> {% for article in article_list %} <p>{{ article.headline }}</p> <p>Autor: {{ article.reporter.full_name }}</p> <p>Opublikowano dnia {{ article.pub_date|date:"Y-m-d" }}</p> {% endfor %} {% endblock %}

Zmienne otaczają podwójne nawiasy klamrowe. Element {{ article.headline }} oznacza “W tym miejscu wyświetl zawartość atrybutu headline artykułu”. Kropek nie uŜywa się tylko i wyłącznie pobierania atrybutów: mogą równieŜ słuŜyć do pobierania danych ze słownika, danych z indeksu lub wywoływania funkcji. ZauwaŜ, Ŝe {{ article.pub_date|date:"Y-m-d" }} wykorzystuje Uniksowy znak potoku (znak “|”). To tak zwany filtr szablonu, który umoŜliwia konwersję wartości zmiennej. W tym przypadku filtr daty formatuje datę zawartą w obiekcie daty na wskazany tekst (format przypomina funkcję date z PHP; tak, to jedna z dobrych cech PHP). MoŜliwe jest tworzenie łańcucha filtrów. MoŜesz napisać własne filtry. MoŜesz napisać własne znaczniki szablonów, które wykonują dowolny napisany przez Ciebie kod Pythona. Django stosuje pojęcie “dziedziczenia szablonów”. To właśnie tym zajmuje się fragment {% extends "base.html" %}. Oznacza on: “Najpierw załaduj szablon o nazwie ‘base’, który ma zdefiniowaną określoną liczbę bloków, a następnie zastąp oryginalne bloki poniŜszym kodem”. W duŜym skrócie moŜemy powiedzieć, Ŝe takie rozwiązanie drastycznie zmniejsza powtarzanie kodu w szablonach: kaŜdy szablon definiuje tylko to, co jest w nim unikatowe. Oto przykładowy wygląd szablonu “base.html”:
<html> <head> <title>{% block title %}{% endblock %}</title> </head> <body> <img src="sitelogo.gif" alt="Logo" /> {% block content %}{% endblock %} </body> </html>

Szablon definiuje ogólny wygląd witryny (razem z logo), a takŜe wskazuje “dziury” do wypełnienia przez szablony potomne. Takie rozwiązanie znacząco upraszcza zmianę wyglądu witryny, bo wielu sytuacjach wystarczy zmienić tylko jeden plik — szablon bazowy.

5

UmoŜliwia równieŜ tworzenie wielu wersji danej witryny z róŜnymi szablonami bazowymi przy stosowaniu tych samych szablonów potomnych. Twórcy Django wykorzystali tę technikę do stworzenia całkowicie innej edycji witryny przystosowanej do telefonów komórkowych — zrobili to, tworząc nowy szablon bazowy. Pamiętaj, Ŝe nie musisz uŜywać systemu szablonów Django, jeśli preferujesz inny. Choć system szablonów Django jest dobrze zintegrowany z warstwą modelu Django, nic nie zmusza Cię do jego stosowania. Równie dobrze nikt nie zmusza Cię do stosowania systemu ORM wbudowanego w Django. MoŜesz wykorzystać inny mechanizm warstwy abstrakcji bazodanowej, czytać dane z plików XML, czytać dane z plików tekstowych lub robić cokolwiek innego. KaŜdy element Django — modele, widoki i szablony — jest mocno odseparowany od pozostałych elementów.

To dopiero początek
Niniejszy tekst to bardzo skrótowy opis funkcjonalności dostępnej w Django. Oto niektóre z innych uŜytecznych funkcji:
• • •

System cache integrujący się z memcached i innymi mechanizmami (pliki, baza danych). System rozpowszechniania (en), który umoŜliwia tworzenie plików dla czytników RSS i Atom poprzez pisanie niewielkich klas Pythonowych. Bardziej seksowne funkcje automatycznie generowanego panelu administracyjnego — jest naprawdę rozbudowany.

Następnym oczywistym krokiem jest pobranie Django, przerobienie tutoriala i dołączenie do społeczności. Dziękujemy za zainteresowanie!

6

How to: instalacja Django
Wskazówki na temat instalacji i uruchamiania Django.

Instalacja Pythona
Jako pythonowy framework webowy Django wymaga Pythona. Django moŜe być uruchomiony na Pythonie 2.3 i nowszym. MoŜesz pobrać Pythona ze strony http://www.python.org. Jeśli uŜywasz Linuksa lub Mac OS X najprawdopodobniej masz juŜ go zainstalowanego.

Instalacja Apache i mod_pythona
Jeśli chcesz tylko poeksperymentować z Django, moŜesz ominąć tę część; Django zawiera lekki serwer http, który moŜesz wykorzystać do testowania, przez co nie musisz instalować Apache, dopóki nie będziesz potrzebował serwera produkcyjnego. JeŜeli jednak potrzebujesz serwera produkcyjnego, uŜyj serwera Apache z mod_pythonem. mod_python jest podobny do mod_perla — włącza on kod Pythona do Apache’a i ładuje kod w Pythonie do pamięci przy uruchomieniu serwera. Kod pozostaje w pamięci przez cały czas działania procesu Apache, co niesie ze sobą zysk wydajności w porównaniu do innych ustawień serwera. Upewnij się, Ŝe masz zainstalowanego Apache z aktywnym modułem mod_python. Django wymaga Apache 2.x i mod_pythona 3.x Zobacz How to - uŜywanie Django z mod_pythonem, aby uzyskać więcej informacji w jaki sposób skonfigurować mod_pythona, gdy juŜ jest zainstalowany. Jeśli z jakichś przyczyn nie moŜesz uŜyć mod_pythona, nie ma problemu: Django jest zgodne ze specyfikacją WSGI, co umoŜliwia uruchomienie go na szerokiej gamie platform serwerowych. W celu uzyskania szczegółowych informacji na temat instalacji na poszczególnych platformach zerknij na stronę wiki Server Arrangements.

Uruchomienie bazy danych
Jeśli planujesz uŜywać bazy danych poprzez API Django, upewnij się, Ŝe serwer bazodanowy działa. Django współpracuje z następującymi serwerami: PostgreSQL, MySQL, Oracle i SQLite (przy czym SQLite nie wymaga osobnego procesu serwera bazy danych). Ponadto sprawdź, czy są zainstalowane odpowiednie sterowniki bazy danych.

Dla PostgreSQL potrzebujesz pakietu psycopg. Django wspiera zarówno wersję 1 jak i 2 (przy konfiguracji warstwy bazodanowej w Django, dla wersji 1 ustaw postgresql, a dla wersji 2 postgresql_psycopg2).

7

Jeśli pracujesz na Windowsie sprawdź nieoficjalne wersje skompilowane na Windows.

Jeśli uŜywasz MySQL, będziesz potrzebować MySQLdb, w wersji 1.2.1p2 lub wyŜszej. Zapewne zainteresują Cię teŜ notki specyficzne dla tej bazy, zawarte na stronie MySQL backend. Jeśli uŜywasz SQLite i Pythona w wersji 2.3 bądź 2.4, będziesz potrzebować pysqlite. UŜyj wersji 2.0.3 lub wyŜszej. Python 2.5 rozprowadzany jest z wrapperem sqlite w bibliotece standardowej, więc nie musisz w tym przypadku instalować nic ponadto. Jeśli uŜywasz Oracle, będziesz potrzebować cx_Oracle, w wersji 4.3.1 bądź wyŜszej. Zapewne zainteresują Cię teŜ notki specyficzne dla tej bazy, zawarte na stronie Oracle backend.

Jeśli planujesz uŜywać djangowego polecenia manage.py syncdb w celu zautomatyzowania procesu tworzenia tabel w bazie danych dla Twojego modelu, będziesz musiał mieć pewność, Ŝe Django ma uprawnienia do tworzenia i modyfikowania tabel w uŜywanej przez ciebie bazie danych. Jeśli planujesz tworzyć tabele ręcznie, moŜesz zwyczajnie nadać Django uprawnienia SELECT, INSERT, UPDATE i DELETE. W przypadku niektórych baz danych Django będzie potrzebować uprawnień do ALTER TABLE w czasie wykonywania syncdb, lecz nie wpłynie to na deklarację ALTER TABLE tabeli która została utworzona przez syncdb. Jeśli uŜywasz frameworka testowego Django by zbadać zapytania do bazy danych, będziesz potrzebować uprawnień do utworzenia testowej bazy danych.

Usuń wszelkie stare wersje Django
Jeśli uaktualniasz swoją instalację Django ze starszej wersji, będziesz musiał odinstalować starą wersję przed instalacją nowej. Jeśli zainstalowałeś Django przy uŜyciu setup.py install, zwyczajnie je odinstaluj usuwając katalog django z site-packages. Jeśli zainstalowałeś Django z pythonowego pakietu egg, usuń plik .egg z Django i odniesienie do tego pliku z pliku easy-install.pth. Plik ten równieŜ powinien znajdować się w Twoim katalogu site-packages. Gdzie się znajduje mój katalog site-packages? PołoŜenie katalogu site-packages zaleŜy od rodzaju systemu operacyjnego i połoŜenia katalogu w którym został zainstalowany Python. Aby odnaleźć połoŜenie site-packages w swoim systemie wykonaj poniŜsze polecenie:
python -c "from distutils.sysconfig import get_python_lib; \ print get_python_lib()"

(ZauwaŜ, Ŝe powyŜsza komenda powinna zostać wykonana w środowisku powłoki systemowej, nie w trybie interaktywnym Pythona)

Instalacja kodu Django
8

Instrukcje instalacyjne mogą się delikatnie róŜnić, w zaleŜności od tego czy instalujesz Django z paczek dla określonej dystrybucji, pobierasz ostatnie oficjalne wydanie czy moŜe ostatnią wersję rozwojową. Bez względu na to jaką metodę wybierzesz, instalacja Django jest naprawdę prosta.

Instalacja z paczek dla określonych dystrybucji
Sprawdź notki specyficzne dla określonych dystrybucji aby przekonać się, czy Twoja platforma/dystrybucja nie zapewnia oficjalnych paczek/instalatorów Django. Paczki dostarczone przez Twoją dystrybucję zazwyczaj umoŜliwiają automatyczną instalację wraz z zaleŜnościami i łatwe uaktualnianie ścieŜek.

Instalacja oficjalnego wydania
1. Pobierz ostatnią wersję ze strony download. 2. Rozpakuj ściągnięte archiwum (np. za pomocą tar xzvf Django-NNN.tar.gz gdzie NNN jest numerem wersji ostatniego wydania). Jeśli uŜywasz Windows moŜesz pobrać działające w linii poleceń narzędzie bsdtar lub uŜyć narzędzia z GUI, takiego jak 7zip. 3. Zmień bieŜący katalog na utworzony w kroku 2 (np. cd Django-NNN). 4. Jeśli uŜywasz Linuksa, Mac OS X lub inny system uniksopodobny wprowadź w linię poleceń sudo python setup.py install. Jeśli uŜywasz Winsows, uruchom powłokę poleceń z uprawnieniami administratora i wykonaj polecenie setup.py install. Te polecenia zainstalują Django w katalogu site-packages Twojej instalacji Pythona.

Instalacja wersji rozwojowej
Jeśli chciałbyś móc uaktualniać swój kod Django sporadycznie po poprawieniu ostatnich bugów i wprowadzenia usprawnień, podąŜaj za tymi instrukcjami: 1. Upewnij się, Ŝe masz zainstalowane Subversion i moŜesz wykonywać jego komendy ze środowiska powłoki (aby to przetestować wprowadź svn help w linię poleceń). 2. Pobierz główną gałąź rozwojową Django (‘trunk’) za pomocą:
3. svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk

4. Następnie zadbaj o to by interpreter Pythona mógł załadować kod Django. Jest wiele sposobów na wykonanie tej czynności. Jednym z najwygodniejszych na Linuksie, Mac OSX lub innym systemie uniksopodobnym jest uŜycie linka symbolicznego:
5. ln -s `pwd`/django-trunk/django SITE-PACKAGES-DIR/django

(W powyŜszej linii zmień SITE-PACKAGES-DIR tak by pasował do lokalizacji katalogu site-packages w Twoim systemie, co zostało wytłumaczone w sekcji powyŜej “Gdzie się znajduje mój katalog site-packages?”.) Alternatywnie, moŜesz zdefiniować swoją zmienną systemową PYTHONPATH tak by zawierała katalog django-trunk. MoŜe być to najwygodniejsze rozwiązanie dla uŜytkowników systemu Windows, który nie spiera linków symbolicznych (zmienne środowiskowe mogą być definiowane w systemie Windows z Panelu Sterowania). 9

Co z Apache i mod_pythononem? Jeśli wybrałeś rozwiązanie z ustawieniem zmiennej PYTHONPATH, musisz pamiętać by zrobić to samo w konfiguracji Apache przy wdroŜeniu w środowisku produkcyjnym. Ustaw PythonPath w pliku konfiguracyjnym Apache. Więcej informacji o wdraŜaniu jest dostępnych w naszej dokumentacji Jak uŜywać Django z mod_pythonem. 6. Na systemach uniksopodobnych utwórz link symboliczny do pliku djangotrunk/django/bin/django-admin.py w katalogu w twojej ścieŜce systemowej, takim jak /usr/local/bin. Na przykład:
7. ln -s `pwd`/django-trunk/django/bin/django-admin.py /usr/local/bin

Zabieg ten pozwala wpisać django-admin.py z poziomu kaŜdego katalogu zamiast wpisywania polecenia z pełną ścieŜką do pliku. Na systemie Windows moŜna osiągnąć ten sam rezultat kopiując plik djangogdziekolwiek w swojej ścieŜce systemowej,

trunk/django/bin/django-admin.py np. C:\Python24\Scripts.

Nie musisz uruchamiać python setup.py install, poniewaŜ dopiero co wykonałeś równowaŜne działania w kokach 3 i 4. Jeśli chcesz uaktualnić swoją kopię kodu źródłowego Django, po prostu wykonaj polecenie svn update z wnętrza katalogu django-trunk. Subversion automatycznie pobierze wszelkie zmiany.

10

Twoja pierwsza aplikacja w Django, część 1
Uczmy się na przykładach. W tym tutorialu przejdziemy przez kolejne kroki tworzenia prostego systemu ankiet. Składa się on z dwóch części:
• •

Publicznej - gdzie wyświetlane są ankiety i moŜna na nie głosować. Administracyjnej - która pozwala na dodawanie, edytowanie i usuwanie ankiet.

Zakładam, Ŝe posiadasz juŜ zainstalowane Django. MoŜesz to sprawdzić uruchamiając interaktywny interpreter Pythona i wpisując import django. Jeśli to się powiedzie, bez Ŝadnych komunikatów błędów, oznacza to Ŝe posiadasz poprawnie zainstalowane Django. Gdzie szukać pomocy: Jeśli masz problemy podczas przerabiania tego tutoriala, moŜesz napisać wiadomość na django-users lub dołączyć do kanału #django na serwerze irc.freenode.net gdzie spróbujemy Ci pomóc.

Tworzenie projektu
Jeśli to Twój pierwszy kontakt z Django, poświęć chwilę na początkową konfigurację. Oznacza to, Ŝe będziesz musiał wygenerować kawałek kodu, który będzie projektem Django — zbiorem ustawień dla instancji Django, włączając w to konfigurację połączenia z bazą danych, opcji specyficznych dla Django i Twojej aplikacji. W linii poleceń, wykonaj komendę cd aby przejść do katalogu gdzie chciałbyś trzymać swój kod, następnie wpisz django-admin.py startproject mysite. Stworzysz w ten sposób katalog mysite w bieŜącym katalogu. Uprawnienia w Mac OS X Jeśli uŜywasz Mac OS X, moŜesz zobaczyć komunikat “permission denied” podczas próby wykonania django-admin.py startproject. Jest to spowodowane tym, Ŝe w systemach Uniksowych jak OS X, plik musi być oznaczony jako “wykonywalny” zanim moŜe zostać uruchomiony jako program. Aby to poprawić, otwórz Terminal.app, przejdź (uŜywając Komendy cd) do katalogu gdzie jest zainstalowany plik django-admin.py i wykonaj komendę chmod +x django-admin.py. Note Powinieneś unikać nazywania projektów nazwami wbudowanych w Pythona lub nazwami komponentów Django. W szczególności oznacza to unikanie nazw takich jak django (która będzie kolidować z samym Django) lub site (która spowoduje konflikt z wbudowanym w Pythona pakietem).

11

(Jeśli instalowałeś Django poprzez python setup.py, django-admin.py powinno znajdować się w twojej ścieŜce systemowej. Jeśli tak nie jest, powinieneś ją znaleźć w sitepackages/django/bin, gdzie site-packages jest katalogiem z instalacją Pythona. RozwaŜ moŜliwość utworzenia dowiązania symbolicznego do django-admin.py z jednego z folderów znajdujących się w Twojej ścieŜce systemowej, np. z /usr/local/bin.) Gdzie powinien znajdować się kod Django? Jeśli w przeszłości programowałeś w PHP, najprawdopodobniej przywykłeś do umieszczania swojego kodu w document root swojego serwera www (w miejscu takim jak /var/www). Z Django nie powinieneś tego robić. Nie jest dobrym pomysłem umiejscawianie jakiegokolwiek kodu Pythona wewnątrz document root, poniewaŜ stwarza to zagroŜenie moŜliwości oglądania Twojego kodu przez odwiedzających. Nie jest do dobre ze względów bezpieczeństwa. Umieść swój kod w którymkolwiek katalogu poza document root, w takim jak np.
/home/mycode.

Zobaczmy zatem co utworzył nam startproject:
mysite/ __init__.py manage.py settings.py urls.py

Te pliki to:
• __init__.py:

• • •

Pusty plik informujący Pythona o tym, Ŝe katalog nadrzędny powinien być traktowany jako pakiet Pythona (zobacz więcej na temat pakietów). manage.py: Działające z linii poleceń narzędzie, które pozwala na interakcję z projektem Django na róŜne sposoby. settings.py: Ustawienia/konfiguracja dla tego projektu Django. urls.py: Deklaracja adresów URL dla tego projektu Django; “mapa serwisu” Twojej strony zbudowanej w oparciu o Django.

Serwer deweloperski
Sprawdźmy czy działa. Przejdź do katalogu mysite, o ile jeszcze w nim nie jesteś i uruchom polecenie python manage.py runserver. Powinieneś zobaczyć następujący tekst na wyjściu linii poleceń:
Validating models... 0 errors found. Django version 1.0, using settings 'mysite.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).

Właśnie wystartowałeś serwer deweloperski Django, lekki serwer www napisany w całości w Pythonie. Dołączyliśmy go do Django byś mógł rozwijać swój kod moŜliwie szybko, bez

12

potrzeby konfiguracji serwera produkcyjnego — takiego jak Apache — do momentu, aŜ będziesz gotowy do wdroŜenia produkcyjnego. Nadszedł dobry moment by zauwaŜyć: NIE UśYWAJ tego serwera do niczego co choćby przypomina środowisko produkcyjne. Jest on przeznaczony jedynie do pomocy w procesie rozwijania własnego kodu (naszą pracą jest tworzenie frameworków sieciowych a nie serwerów www). Teraz, kiedy serwer jest uruchomiony, odwiedź http://127.0.0.1:8000/ za pomocą swojej przeglądarki internetowej. Powinieneś zobaczyć stronę powitalną, w miłych, jasnoniebieskich pastelowych kolorach. To działa! Zmiana portu Domyślnie polecenie runserver uruchamia serwer deweloperski na porcie 8000. Jeśli chcesz zmienić port serwera, prześlij jego wartość jako argument przy wywołaniu z linii poleceń. Dla przykładu - to polecenie uruchamia serwer na porcie 8080:
python manage.py runserver 8080

Pełna dokumentacja dla serwera deweloperskiego znajduje się na stronie dokumentacji panelu admina.

Ustawienia bazy danych
Teraz moŜemy przejść do edycji settings.py. Jest to zwykły moduł Pythona zawierający zmienne reprezentujące ustawienia Django. Ustaw następujące parametry tak, aby odzwierciedlały konfigurację Twojej bazy danych:
• • • • • DATABASE_ENGINE — ‘postgresql_psycopg2’, ‘mysql’ lub ‘sqlite3’. Inne backendy są równieŜ dostępne. DATABASE_NAME — Nazwa Twojej bazy danych, bądź absolutna ścieŜka do pliku bazy danych, jeśli uŜywasz SQLite. DATABASE_USER — Nazwa uŜytkownika uprawnionego do połączenia z bazą danych (nie uŜywane w SQLite). DATABASE_PASSWORD — Hasło dostępu do bazy danych (nie uŜywane w SQLite). DATABASE_HOST — Adres serwera bazy danych. MoŜesz zostawić puste jeśli serwer bazy danych znajduje się na tym samym komputerze co Twoja aplikacja (nie uŜywane w SQLite).

Uwaga Jeśli uŜywasz MySQL lub PostgreSQL, upewnij się Ŝe stworzyłeś potrzebną bazę danych. MoŜesz to wykonać poleceniem “CREATE DATABASE database_name;” z wnętrza powłoki trybu aktywnego swojej bazy danych. Edytując plik settings.py zwróć uwagę na ustawienia INSTALLED_APPS znajdujące się na samym dole. Ta zmienna przechowuje nazwy wszystkich aplikacji Django, które są aktywowane w bieŜącej instancji Django. Aplikacje mogą być uŜywane w wielu projektach -

13

moŜesz tworzyć z nich pakiety i rozpowszechniać je aby inni mogli ich uŜywać w swoich projektach. Domyślnie INSTALLED_APPS zawiera następujące aplikacje, wszystkie pochodzące od Django:
• • • • django.contrib.auth — System uwierzytelniania. django.contrib.contenttypes — Framework do trzymania typów modeli. django.contrib.sessions — Framework sesji. django.contrib.sites — Framework do zarządzania wieloma stronami w jednej

instalacji Django. Te aplikacje są dołączane domyślnie w ramach wygody dla powszechnych przypadków uŜycia. KaŜda z tych aplikacji uŜywa co najmniej jednej tabeli w bazie danych, które naleŜy utworzyć przed ich uŜyciem. By to zrobić, wywołaj następujące polecenie:
python manage.py syncdb

Komenda syncdb patrzy na ustawienia INSTALLED_APPS i tworzy wszystkie potrzebne tabele w bazie z uwzględnieniem ustawień odnośnie baz danych w Twoim pliku settings.py. Powinieneś zobaczyć informację o kaŜdej utworzonej przez niego tabeli i otrzymać zapytanie o utworzenie konta superuŜytkownika dla systemu uwierzytelniania. MoŜesz śmiało na to się zgodzić. Jeśli jesteś zainteresowany, uruchom klienta linii poleceń swojej bazy danych i wpisz \dt (PostgreSQL), SHOW TABLES; (MySQL) lub .schema (SQLite) celem wyświetlenia tabel utworzonych przez Django. Dla minimalistów Jak wcześniej wspomnieliśmy, domyślne aplikacje są dołączone dla najpowszechniejszych zastosowań, ale nie kaŜdy ich potrzebuje. Jeśli nie potrzebujesz którejś lub wszystkich moŜesz zwyczajnie je za komentować lub usunąć odpowiadające jej/im linie z INSTALLED_APPS przed uruchomieniem syncdb. Komenda syncdb utworzy jedynie tabele dla aplikacji wymienionych w INSTALLED_APPS.

Tworzenie modeli
Teraz, kiedy twoje środowisko — jako “projekt” — jest ustawione, jesteś gotowy by zacząć pracę nad projektem. KaŜda aplikacja, którą piszesz w Django, opiera się na pakietach Pythona, leŜących gdzieś w Twojej ścieŜce dostępu Pythona, co wynika z pewnych konwencji. Na szczęście Django zapewnia zestaw narzędzi, które automatycznie generują podstawową strukturę aplikacji, więc moŜesz skupić się raczej na pisaniu kodu zamiast na tworzeniu katalogów. Projekty kontra aplikacje

14

Jaka jest róŜnica pomiędzy projektem a aplikacją? Aplikacja coś robi — jest nią np. system blogowy, rejestr danych publicznych lub prosta ankieta. Projekt jest kolekcją konfiguracji i aplikacji dla określonej strony www. Projekt moŜe zawierać wiele aplikacji. Dana aplikacja moŜe być w wielu projektach. W tym tutorialu dla ułatwienia utworzymy aplikację ankiety w katalogu mysite. W konsekwencji aplikacja będzie połączona z projektem — to znaczy kod aplikacji ankiety będzie odnosił się do aplikacji mysite.polls. Dalej w tym tutorialu omówimy jak uniezaleŜnić Twoją aplikację od dystrybucji. Aby utworzyć aplikację, upewnij się Ŝe jesteś wewnątrz katalogu mysite i wprowadź następujące polecenie:
python manage.py startapp polls

To utworzy katalog polls, którego zawartość wygląda mniej więcej tak:
polls/ __init__.py models.py views.py

Ta struktura katalogu będzie przechowywać kod źródłowy aplikacji ankiety. Pierwszym krokiem w pisaniu aplikacji www korzystającej z bazy danych w Django jest zdefiniowanie modeli — układ w bazie danych z dodatkowymi metadanymi. Filozofia Model jest pojedynczym, definiującym źródłem na temat Twoich danych. Zawiera istotne pola i definiuje zachowania danych przez Ciebie przechowywanych. Django podąŜa za Regułą DRY. Celem jest zdefiniowanie Twojego modelu danych w jednym miejscu i automatyczne pobieranie z niego potrzebnych informacji. W naszej sondzie stworzymy dwa modele: sondy (Poll) i odpowiedzi (Choice). Sonda zawiera pytanie (question) i datę publikacji (pub_date), natomiast kaŜda z odpowiedzi posiada pola: treść odpowiedzi (choice) i liczbę oddanych głosów (votes). KaŜda odpowiedź jest powiązana z konkretną sondą. Te załoŜenia są odwzorowane przez klasy napisane w Pythonie. Poddaj edycji plik aby wyglądał tak jak poniŜej:

polls/models.py

from django.db import models class Poll(models.Model): question = models.CharField(max_length=200) pub_date = models.DateTimeField('data publikacji') class Choice(models.Model): poll = models.ForeignKey(Poll) choice = models.CharField(max_length=200) votes = models.IntegerField()

15

Błędy spowodowane max_length Jeśli Django wyrzuca komunikaty błędów mówiące Ŝe max_length nie jest poprawnym argumentem, najprawdopodobniej uŜywasz starej wersji Django (ta wersja tutoriala została napisana dla najnowszej, rozwojowej wersji Django). Jeśli korzystasz z rozwojowej wersji Django z Subversion (zobacz dokumentację instalacyjną by uzyskać więcej informacji), nie powinieneś mieć z tym Ŝadnych problemów. Jeśli chcesz pozostać ze starszą wersją Django, będziesz musiał przejść do tutoriala dla Django 0.96, poniewaŜ ten tutorial omawia kilka właściwości które istnieją jedynie w wersji rozwojowej. Kod jest samo wyjaśniający się. KaŜdy model jest reprezentowany przez podklasę, która dziedziczy z klasy django.core.meta.Model. KaŜdy model posiada pewną liczbę zmiennych, z których kaŜda reprezentuje pole w bazie danych. KaŜde pole jest reprezentowane jako instancja klasy meta.*Field — np. models.CharField dla pól tekstowych i models.DateTimeField` dla obiektów datetime. Fakt ten pozwala Django stwierdzić, jakiego typu dane są przechowywane przez kaŜde z pól. Nazwa kaŜdej z instancji meta.*Field (np. question lub pub_date) jest nazwą pola, taką jakiej oczekuje komputer. Będziesz uŜywać tych nazw w swoim kodzie, a Twoja baza danych będzie uŜywać ich jako nazwy kolumn. MoŜesz teŜ uŜyć opcjonalnego parametru dla pola aby przypisać mu dowolną, przyjazną człowiekowi nazwę. Jest to uŜywane podczas introspekcji róŜnych części Django, a takŜe w dokumentacji. JeŜeli tego pola nie ma, Django będzie uŜywać nazwy zmiennej. W naszym przykładzie zdefiniowaliśmy tylko jedną przyjazną dla uŜytkownika nazwę, dla pola Poll.pub_date. Dla wszystkich innych pól w tym modelu, nazwy zmiennych są wystarczająco czytelne dla człowieka. Niektóre klasy Field wymagają podania pewnych atrybutów. Klasa CharField na przykład oczekuje parametru max_length. Jest on uŜywany nie tylko przy tworzeniu struktury bazy danych, ale takŜe podczas weryfikacji poprawności danych, o czym się niedługo sam przekonasz. Na koniec zauwaŜ, Ŝe zostały zdefiniowane takŜe relacje między klasami za pomocą models.ForeignKey. To mówi Django o powiązaniach między kaŜdą z odpowiedzi a konkretną sondą. Django obsługuje powiązania: wiele-do-jednego (many-to-one), wiele-dowielu (many-to-many) i jeden-do-jednego (one-to-one).

Aktywacja modeli
Ta mała część kodu modelu dostarcza Django mnóstwa informacji. Z jego pomocą, Django moŜe:
• •

Stworzyć strukturę bazy danych (wygenerować kwerendy CREATE TABLE) dla tworzonej aplikacji. Stworzyć API dostępu do bazy danych dla obiektów Poll i Choice.

16

Ale najpierw, musimy poinformować nasz projekt Ŝe aplikacja polls (sonda) została zainstalowana. Filozofia Aplikcje Django są wtyczkami (pluginami): moŜesz uŜywać ich w wielu projektach, a takŜe rozpowszechniać, poniewaŜ nie są one przypisane do konkretnej instalacji Django. Wyedytuj ponownie plik settings.py, i dopisz do INSTALLED_APPS mysite.polls. Teraz powinno to wyglądać tak:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'mysite.polls' )

Django wie teraz, Ŝe mysite zawiera aplikację polls. Wykonaj teraz inną komendę:
python manage.py sql polls

Treaz powinieneś zobaczyć następujący ciąg poleceń CREATE TABLE dla Twojej ankiety:
BEGIN; CREATE TABLE "polls_poll" ( "id" serial NOT NULL PRIMARY KEY, "question" varchar(200) NOT NULL, "pub_date" timestamp with time zone NOT NULL ); CREATE TABLE "polls_choice" ( "id" serial NOT NULL PRIMARY KEY, "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"), "choice" varchar(200) NOT NULL, "votes" integer NOT NULL ); COMMIT;

ZauwaŜ Ŝe:
• •

• • • •

Konkretna wartość wyjściowa będzie zaleŜeć od bazy danych jakiej uŜywasz. Nazwy tabel są generowane automatycznie poprzez kombinację nazwy aplikacji (polls) i nazwy modelu zapisanej małymi literami — poll i choice (moŜesz zmienić to domyślne zachowanie). Klucze główne (ID) są dodawane automatycznie (aczkolwiek moŜesz to zmienić). Django dodaje końcówkę "_id" do zazw pól kluczy obcych (ForeignKey). RównieŜ to zachowanie moŜesz jednak zmienić. Powiązania z uŜyciem kluczy obcych są tworzone poprzez deklarację REFERENCES. To jest ściśle powiązane z bazą danych której uŜywasz, więc polecenia takie jak auto_increment (MySQL), serial (PostgreSQL) lub integer primary key (SQLite) specyficzne dla danego typu bazy są ustawiane automatycznie. To samo dotyczy się cytowania nazw pół — w zaleŜności od bazy danych uŜywa się

17

pojedynczych bądź podwójnych cudzysłowów. Autor tego wprowadzenia uŜywa PostgreSQL, tak więc przykłady są napisane dla tej bazy. Komenda sql nie wykonuje zapytań SQL na twoje bazie danych - jedynie drukuje je na ekranie byś mógł zobaczyć jaki SQL Django uwaŜa na wymagany. Jeśli chcesz, moŜesz skopiować i wkleić ten fragment kodu SQL na wejście trybu interaktywnego swojej bazy danych. JednakŜe, jak wkrótce zobaczymy, Django zapewnia prostą metodę zatwierdzania tego SQL-a do Twojej bazy danych.

Jeśli jesteś zainteresowany, moŜesz takŜe uruchomić poniŜsze komendy:
• •

• •

— Sprawdza Twój model w poszukiwaniu jakichkolwiek błędów konstrukcyjnych. python manage.py sqlcustom polls — Wypisuje wszelkie własne zapytania SQL (takie jak modyfikacja tabeli lub ograniczenia (ang. constraints)) które są definiowane przez aplikacje. python manage.py sqlclear polls — Wypisuje wymagane wyraŜenia DROP TABLE dla tej aplikacji, biorąc pod uwagę aktualnie istniejące tabele w Twojej bazie danych (jeśli takowe istnieją). python manage.py sqlindexes polls — Wypisuje wyraŜenie CREATE INDEX dla tej aplikacji. python manage.py sqlall polls — Kombinacja wszystkich wyjściowych wartości wyraŜeń SQL z poleceń ‘sql’, ‘sqlcustom’ i ‘sqlindexes’.
python manage.py validate

Przejrzenie wyników powyŜszych komend pomoŜe Ci zrozumieć, co się dzieje “pod podszewką” Django. Wykonaj teraz syncdb ponownie by utworzyć tabele tych modeli w Twojej bazie danych:
python manage.py syncdb

Komenda syncdb uruchamia polecenie SQL z ‘sqlall’ na Twojej bazie danych dla wszystkich aplikacji z INSTALLED APPS które nie istnieją aktualnie w Twojej bazie danych. Polecenie to tworzy wszystkie tabele, inicjalizuje dane i indeksuje dla kaŜdej aplikacji którą dodałeś do projektu od momentu ostatniego uruchomienia komendy syncdb. syncdb moŜe być wykonywane przez Ciebie tak często, jak Ci się to podoba tworząc tabele tylko wtedy, gdy nie istnieją. Przeczytaj dokumentację django-admin.py dowiedzieć się o pełnych moŜliwościach manage.py.

Zabawy z API
Przejdź teraz do interaktywnej powłoki Pythona i poćwicz nieco wykorzystanie API dostarczone przez Django. By uruchomić powłokę Pythona uruchom komendę:
python manage.py shell

UŜywamy jej zamiast zwykłego polecenia “python”, poniewaŜ manage.py ustawia środowisko projektu za nas. “Ustawienie środowiska” polega na dwóch rzeczach:

18

Dodaniu mysite do sys.path. Dla elastyczności, kilka fragmentów Django odnosi się do projektów w Pythonie stosując notację z kropką (np. 'mysite.polls.models'). W związku z tym pakiet mysite musi znajdować się w system.path. Niedawno widzieliśmy przykład takiego uŜycia: INSTALLED APPS przechowuje listę pakietów we wspomnianej notacji z kropką.

Ustawieniu zmiennej DJANGO_SETTINGS_MODULE, która zapewnia Django ścieŜkę do Twojego pliku settings.py.

Praca bez wykorzystania manage.py Jeśli nie chcesz uŜywać manage.py nie ma problemu. Po prostu upewnij się, Ŝe mysite na głównym poziomie ścieŜki dostępu Pythona (import mysite działa) i ustawia zmiennej środowiskowej DJANGO_SETTINGS_MODULE wartość mysite.settings. W celu uzyskania większej ilości informacji zobacz dokumentację django-admin.py. Gdy juŜ będziesz w shellu zbadaj API bazy danych:
# Zaimportuj modele klas które uprzednio napisaliśmy. >>> from mysite.polls.models import Poll, Choice # Na chwilę obecną nie ma w systemie Ŝadnych ankiet. >>> Poll.objects.all() [] # Utwórz nową ankietę Poll. >>> import datetime >>> p = Poll(question="Jak leci?", pub_date=datetime.datetime.now()) # Zapisz obiekt w bazie danych. Musisz wywołać metodę save() jawnie. >>> p.save() # Teraz ma on swoje ID. ZauwaŜ, Ŝe moŜe ono mieć wartość "1L" zamiast "1", # w zaleŜności od tego jakiej bazy danych uŜywasz. To jednak drobnostka; # oznacza to jedynie tyle, Ŝe Twoja baza danych woli zwracać typ integer # jako obiekt long integer Pythona. >>> p.id 1 # Dostęp do kolumn następuje przez atrybuty Pythona. >>> p.question "Jak leci?" >>> p.pub_date datetime.datetime(2007, 7, 15, 12, 00, 53) # Pozmieniaj wartości zmieniając atrybuty i wywołując metodę save(). >>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0) >>> p.save() # objects.all() wyświetla wszystkie ankiety w bazie danych. >>> Poll.objects.all() [<Poll: Poll object>]

19

Chwila. <Poll: Poll object> jest wyświetlany w formie mało pomocnej reprezentacji tego obiektu. Naprawmy to poprzez edycję modelu sondy (opisanego w pliku polls/models.py) i przeciąŜeniu metody __unicode__() w klasach Poll i Choice:
class Poll(models.Model): # ... def __unicode__(self): return self.question class Choice(models.Model): # ... def __unicode__(self): return self.choice

Gdy __unicode__() wydaje się nie działać Jeśli dodałeś do swoich modeli metodę __unicode__() i nie widzisz Ŝadnej zmiany w tym jak są reprezentowane, najprawdopodobniej uŜywasz starej wersji Django (ta wersja tutoriala została napisana dla najnowszej, rozwojowej wersji Django). Jeśli korzystasz z rozwojowej wersji Django z Subversion (zobacz dokumentację instalacyjną by uzyskać więcej informacji), nie powinieneś mieć z tym Ŝadnych problemów. Jeśli chcesz pozostać ze starszą wersją Django, będziesz musiał przejść do tutoriala dla Django 0.96, poniewaŜ ten tutorial omawia kilka właściwości które istnieją jedynie w wersji rozwojowej. PrzeciąŜanie metody __unicode__() w modelach jest waŜne nie tylko z powodu zwiększenia czytelności przy uŜywaniu powłoki interaktywnej, ale takŜe poniewaŜ reprezentacje obiektów są uŜywane przez Django w automatycznie generowanym panelu administracyjnym. Dlaczego __unicode__() a nie __str__()? Jeśli jesteś obeznany z Pythonem, moŜesz mieć nawyk dodawania do swoich klas metody __str__() a nie __unicode__(). UŜywamy __unicode__() poniewaŜ modele Django mają domyślnie do czynienia z unikodem. Wszelkie dane trzymane w twojej bazie danych są konwertowane do unikodu zaraz po ich wyciągnięciu. Domyślna metoda __str__() modeli Django wywołuje __unicode__() i konwertuje rezultat na bytestringa UTF-8. Oznacza to, Ŝe unicode(p) zwraca ciąg znaków Unicode, zaś str(p) zwraca normalny ciąg znaków zakodowany jako UTF-8. Jeśli wszystko co zostało wcześniej napisane nie ma dla Ciebie większego sensu, po prostu pamiętaj dodać do swoich modeli metodę __unicode__(). Z odrobiną szczęścia wszystko powinno po prostu działać. Zwróć uwagę, Ŝe są to zwykłe metody Pythona. Dla celów demonstracyjnych dodajmy własną metodę:
import datetime # ... class Poll(models.Model): # ...

20

def was_published_today(self): return self.pub_date.date() == datetime.date.today()

ZauwaŜ, Ŝe dodatkowa linia import datetime odnosi się do standardowego modułu Pythona datetime. Przejdźmy z powrotem do interaktywnej powłoki Pythona uruchamiając ponownie python
manage.py shell: >>> from mysite.polls.models import Poll, Choice # Upewnij się Ŝe dodana przez nas metoda __unicode__() działa. >>> Poll.objects.all() [<Poll: Jak leci?>] # Django zapewnia bogate API bazy danych, które w całości napędzane jest # nazywanymi argumentami >>> Poll.objects.filter(id=1) [<Poll: Jak leci?>] >>> Poll.objects.filter(question__startswith='Jak') [<Poll: Jak leci?>] # Pobierz ankietę, której rok wynosi 2007. Oczywiście jeśli wcześniej # w trakcie tego tutoriala wybrałeś inną datę, powinieneś w tym momencie # wprowadzić odpowiednią wartość. >>> Poll.objects.get(pub_date__year=2007) <Poll: Jak leci?> >>> Poll.objects.get(id=2) Traceback (most recent call last): ... DoesNotExist: Poll matching query does not exist. # Poszukiwanie obiektu na podstawie wartości klucza głównego jest # najczęściej stosowanym przypadkiem, dlatego Django zapewnia odpowiednią # metodę. # PoniŜsze jest identyczne z Poll.objects.get(id=1). >>> Poll.objects.get(pk=1) <Poll: Jak leci?> # Upewnij się Ŝe zdefiniowana przez Ciebie metoda działa. >>> p = Poll.objects.get(pk=1) >>> p.was_published_today() False # Dołącz do ankiety (Poll) kilka odpowiedzi (Choices). Wywołanie # konstruktora tworzy nowy obiekt odpowiedzi, wykonuje polecenie INSERT, # dodaje odpowiedź do listy dostępnych odpowiedzi i zwraca nowy obiekt # odpowiedzi (Choice). >>> p = Poll.objects.get(pk=1) >>> p.choice_set.create(choice='Specjalnie nic nowego', votes=0) <Choice: Specjalnie nic nowego> >>> p.choice_set.create(choice='Ciurkiem', votes=0) <Choice: Ciurkiem> >>> c = p.choice_set.create(choice='Znowu programuję', votes=0) # Obiekty wyboru (Choice) posiadają API zapewniające dostęp do związanych # z nimi obiektami ankiety (Polls). >>> c.poll <Poll: Jak leci?>

21

# I odwrotnie: obiekty Poll posiadają dostęp do obiektów Choice. >>> p.choice_set.all() [<Choice: Specjalnie nic nowego>, <Choice: Ciurkiem>, <Choice: Znowu programuję>] >>> p.choice_set.count() 3 # Omawiane API automatycznie podąŜa za relacjami tak daleko jak tego # potrzebujesz. UŜyj podwójnego podkreślnika by oddzielić powiązania. # Działa to dla tylu poziomów głębokości dla ilu chcesz - nie ma limitu. # Znajdź wszystkie Odpowiedzi (Choices) dla kaŜdej ankiety opublikowanej # w roku 2007. >>> Choice.objects.filter(poll__pub_date__year=2007) [<Choice: Specjalnie nic nowego>, <Choice: Ciurkiem>, <Choice: Znowu programuję>] # Usuń jedną z odpowiedzi. UŜyj delete() aby tego dokonać. >>> c = p.choice_set.filter(choice__startswith='Znowu program') >>> c.delete()

By uzyskać więcej informacji na temat API do baz danych zobacz dokumentację API do baz danych Gdy juŜ będziesz czuł się komfortowo uŜywając wspomnianego wcześniej API, przeczytaj część 2 tego tutoriala aby dodać automatyczny panel admina.

Pytania/Wsparcie
JeŜeli zauwaŜyłeś błędy w tłumaczeniu dokumentacji proszę zgłoś je nam.

22

Twoja pierwsza aplikacja w Django, część 2
Tłumaczenie: Marcin Sztolcman <marcin {} urzenia // net> Poprawki: Maciej Litwiniuk <maciej // litwiniuk {} galdomedia // pl> Ta część tutoriala zaczyna się w miejscu, w którym skończyła się część pierwsza. Będziemy kontynuować budowę aplikacji webowej - sondy - i skupimy się na automatycznie generowanym panelu administracyjnym. ZałoŜenia Generowanie panelu administracyjnego dla klientów aby mogli dodawać, edytować i usuwać treść jest Ŝmudną pracą która nie wymaga zbyt duŜej kreatywności. Z tego właśnie powodu Django stara się zautomatyzować tworzenie interfejsu administracyjnego. Django był pisany w środowisku publicystów, gdzie bardzo waŜnym było oddzielenie części zarządzającej stroną od publicznej. Osoby zarządzające stroną uŜywają systemu aby dodawać nowe historie, wydarzenia, punktacje sportowe etc, a treść ta była prezentowana czytelnikom. Django rozwiązuje problemy z związane tworzeniem uniwersalnych paneli administracyjnych na potrzeby edycji treści. Panel administracyjny nie jest przeznaczony do uŜytku przez osoby odwiedzające naszą stronę - jest dla osób zarządzających tą stroną.

Aktywacja panelu administracyjnego
Część administracyjna Django jest domyślnie wyłączona - moŜna ją opcjonalnie włączyć. Aby aktywować interfejs administracyjny dla swojej instalacji, trzeba wykonać trzy kroki:
• • •

Dodać "django.contrib.admin" do ustawień INSTALLED_APPS. Wykonać komendę python manage.py syncdb. Jako, Ŝe dodałeś nową aplikację do INSTALLED_APPS, tabele w bazie danych muszą zostać uaktualnione. Popraw swój plik mysite/urls.py oraz odkomentuj linię znajdującą się pod “Uncomment this for admin:”. Ten plik jest plikiem konfiguracyjnym dla URLi Twojej strony - będziemy zgłębiać jego tajniki w następnej części tutoriala. Na tą chwilę wystarczy Ci wiedzieć, Ŝe rzutuje on adresy URL na Twoją aplikację. Po dokonaniu wyŜej opisanych zmian powinieneś plik urls.py który jest podobny do tego:
from django.conf.urls.defaults import * # Odkomentuj dwie linie pod spodem aby włączyć aplikacje admina: from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # Przykład: # (r'^mysite/', include('mysite.foo.urls')),

• • • • • • • • • •

23

• • • • • • • •

# # # #

Odkomentuj linie admin/doc pod spodem oraz dodaj 'django.contrib.admindocs' do INSTALLED_APPS aby włączyć dokumentacje admina: (r'^admin/doc/', include('django.contrib.admindocs.urls')),

# Odkomentuj linie pod spodem aby włączyć aplikacje admina: (r'^admin/(.*)', admin.site.root), )

(Wytłuszczone linie, są liniami które powinny być odkomentowane aby włączyć aplikacje admina)

Uruchomienie serwera deweloperskiego
Uruchommy serwer deweloperski i przyjrzyjmy się stronie administracyjnej. Przypomnij sobie z części pierwszej, Ŝe serwer deweloperski uruchamiałeś poleceniem:
python manage.py runserver

Teraz otwórz przeglądarkę internetową i przejdź do “/admin/” w swojej lokalnej domenie — np. http://127.0.0.1:8000/admin/. Powinieneś zobaczyć ekran logowania do aplikacji administracyjnej.

Obejrzymy panel admina
Spróbuj teraz się zalogować. (Stworzyłeś konto super uŜytkownika w części pierwszej, pamiętasz?) Powinieneś ujrzeć stronę główną panelu administracyjnego Django:

Powinieneś zobaczyć równieŜ kilka innych typów edytowalnych treści, w tym grupy, uŜytkowników oraz strony. To jest podstawowa funkcjonalność, którą Django dostarczana domyślnie.

Modyfikacja sondy z panelu admina
Ale gdzie jest nasza sonda? Nie ma jej przecieŜ w panelu administracyjnym. Trzeba zrobić jedną rzecz: “poinformować” aplikacje admina Django Ŝe obiekty typu Poll mają interface admina. Stwórz plik o nazwie admin.py w Twojej aplikacji polls i zmień go aby wyglądał tak: 24

from django.contrib import admin from mysite.polls.models import Poll admin.site.register(Poll)

Teraz odświeŜ stronę panelu, by zobaczyć zmiany. ZauwaŜ, Ŝe nie musiałeś ponownie uruchomić serwera deweloperskiego — serwer automatycznie przeładuje projekt, więc wszelkie zmiany będą od razu widoczne w Twojej przeglądarce.

Badanie funkcjonalności admina
Teraz, gdy model Poll został zarejestrowany, Django wie, Ŝe ma wyświetlić go w panelu:

Kliknij “Polls”. Jesteś teraz na wykazie wszystkich sond. Ta strona pokazuje wszystkie sondy znajdujące się w bazie danych i pozwala wybrać jedną z nich do edycji. Teraz znajduje się tam tylko “Jak leci?” - czyli sonda którą utworzyliśmy w pierwszej części tutoriala:

Kliknij “Jak leci?” aby poddać ją edycji:

Rzeczy które warto zauwaŜyć:
• •

Formularz został wygenerowany automatycznie na podstawie informacji z modelu sondy róŜnym rodzajom pól modelu (model.DateTimeField, model.CharField) odpowiadają róŜne kontrolki HTML. KaŜdy typ pola wie jak ma zostać wyświetlony w panelu administracyjnym

25

do kaŜdego pola DateTimeField dodawane są dodatkowe przyciski. Dla daty jest to “Today” (“Dzisiaj”) wraz z przyciskiem wyświetlającym okienko z mini kalendarzem, natomiast dla pola “Time” (“Czas”) są przypisane przyciski “Now” (“Teraz”) oraz drugi, słuŜący do pokazania okienka z listą najczęściej uŜywanych określeń czasu.

Dolna część strony daje kilka opcji:
• • • •

Save (Zapisz) — zapisuje zmiany i wraca do listy obiektów danego rodzaju. Save and continue editing (Zapisz i kontynuuj edycję) — zapisuje zmiany i przeładowuje stronę dla tego obiektu Save and add another (Zapisz i dodaj nowe) — zapisuje zmiany i przenosi do nowego, pustego formularza odpowiedniego dla danego rodzaju obiektu. Delete (Usuń) — wyświetla ekran potwierdzający usunięcie obiektu.

Zmień datę publikacji (“Date published”) sondy poprzez kliknięcie skrótów “Today” (“Dzisiaj”) i “Now” (“Teraz”). Następnie kliknij “Save and continue editing” (“Zapisz i kontynuuj edycję”). Teraz wybierz “History” (“Historia”) w prawym górnym rogu strony. Zobaczysz listę zmian dla tego obiektu dokonanych w panelu administracyjnym Django, wraz z datą i godziną zmiany oraz loginem osoby dokonującej tą zmianę:

Dostosowywanie panelu administracyjnego
Poświęć kilka minut na podziwianie kodu, którego wcale nie musiałeś napisać. Kiedy wywołujesz admin.site.register(Poll), Django zgadnie jak ma wyświetlić model w adminie. Często będziesz chciał kontrolować jak admin działa i wygląda. Zrobisz to mówiąc Django jakie opcje chcesz zarejestrować na obiekcie. Poprawmy go nieco. MoŜemy zmienić kolejność pól poprzez dodanie parametru Zobaczmy jak to działa przez zmianę kolejności pól w formularzu edycji. Podmień linie na:

admin.site.register(Poll)

class PollAdmin(admin.ModelAdmin): fields = ['pub_date', 'question'] admin.site.register(Poll, PollAdmin)

Powtórz ten wzorzec — stwórz obiekt model admin, przekaŜ go jako drugi argument do admin.site.register() — za kaŜdym razem gdy chcesz stworzyć opcje admina dla obiektu. To spowodowało przesunięcie pola “Pub date” na górę:

26

Nie ma to większego znaczenia przy tylko dwóch polach, jednak dla formularzy z większą ilością pól ustawienie intuicyjnej kolejności jest waŜne ze względów uŜywalności takiego formularza. A skoro juŜ mówimy o formularzach z większą ilością pól, moŜesz chcieć je podzielić na zestawy:
class PollAdmin(admin.ModelAdmin): fieldsets = [ (None, {'fields': ['question']}), ('Date information', {'fields': ['pub_date']}), ] admin.site.register(Poll, PollAdmin)

Pierwszym elementem w kaŜdej tupli (krotce) w atrybucie fieldsets jest nazwa zestawu. Teraz formularz wygląda tak:

MoŜesz przypisać do kaŜdego zestawu konkretną klasę języka HTML. Django posiada wbudowaną obsługę klasy "collapse" która wyświetla wybrany zestaw pól jako początkowo

27

zwinięte. Jest to uŜyteczne gdy mamy długi formularz z kilkoma polami które są rzadziej uŜywane:
class PollAdmin(admin.ModelAdmin): fieldsets = [ (None, {'fields': ['question']}), ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), ]

Dodawanie obiektów powiązanych
Ok. Mamy juŜ w panelu nasze sondy. Ale kaŜda sonda (Poll) ma kilka odpowiedzi (Choices), a w panelu nie są one wyświetlane. Jeszcze. Są 2 sposoby na naprawienie tego problemu. Pierwszym jest zarejestrowanie obiektu Choice z adminem tak samo jak zrobiliśmy to z obiektem. Tak by to wyglądało:
from mysite.polls.models import Choice admin.site.register(Choice)

Teraz odpowiedzi do sondy są dostępne w panelu. Formularz dodawania odpowiedzi (“Add choice”) wygląda tak:

28

W powyŜszym formularzu pole “Poll” jest polem wyboru zawierającym wszystkie sondy w bazie. Django wie, Ŝe pole ForeignKey powinno być reprezentowane w panelu administracyjnym jako pole <select>. W naszym przypadku tylko jedna sonda chwilowo została zapisana. Zwróć uwagę na odnośnik “Add another” (“Dodaj inną”) znajdujący się obok pola “Poll”. KaŜdy obiekt powiązany kluczem obcym (ForeignKey) z innym obiektem dostaje taki link automatycznie. Jeśli klikniesz “Add another”, zobaczysz okienko (popup) z formularzem do dodawania sond. Jeśli dodasz nową sondę za pomocą tego okienka i klikniesz “Save”, Django zapisze nową sondę w bazie danych oraz uaktualni pole wyboru znajdujące się w formularzu odpowiedzi (“Choice”). PowyŜszy sposób nie jest najbardziej efektywną metodą dodawania obiektów odpowiedzi do systemu. Byłoby wygodniej, jeśli mógłbyś dodawać odpowiedzi do sondy bezpośrednio z formularza w którym tworzysz nową sondę. Skoro tak, to spróbujmy to wykonać. Usuń wywołanie register() dla modelu Choice. Następnie zmień rejestracje modelu Poll:
class ChoiceInline(admin.StackedInline): model = Choice extra = 3 class PollAdmin(admin.ModelAdmin): fieldsets = [ (None, {'fields': ['question']}), ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), ] inlines = [ChoiceInline] admin.site.register(Poll, PollAdmin)

PowyŜsza zmiana informuje Django: “Obiekty odpowiedzi są edytowane z poziomu formularza sond. Domyślnie dostarcz 3 zestawy pól odpowiedzi.” Załaduj stronę “Add poll” Ŝebyśmy mogli sprawdzić jak to wygląda:

29

Działa to w następujący sposób: są tam 3 pola odpowiedzi — jak zostało ustalone przez opcję — ale za kaŜdym razem gdy wrócisz do strony juŜ stworzonego obiektu, dostaniesz kolejne pole odpowiedzi (tzn. nie ma na sztywno ustawionego ograniczenia co do ilości powiązanych obiektów które moŜna dodać).
extra

Jest tylko jeden mały problem: wyświetlenie wszystkich powiązanych wpisów zabiera mnóstwo miejsca na ekranie. Z tego powodu, Django pozwala na inny sposób wyświetlenia wewnętrznie powiązanych obiektów; musisz tylko zmienić deklaracje ChoiceInline:
class ChoiceInline(admin.TabularInline): #...

Z TabularInline (zamiast StackedInline), wtedy powiązane obiekty będą wyświetlane w bardziej skomasowany, tabelaryczny sposób:

Modyfikacja listy obiektów
Teraz, kiedy strony edycji i dodawania sondy wyglądają tak jak powinny, spróbujmy poprawić stronę z listą sond. Tak to wygląda obecnie:

30

Domyślnie, Django pokazuje reprezentację str() kaŜdego obiektu. Oczywiście moŜna to trochę dostosować, tak, Ŝeby wyświetlał poŜądane przez nas pola. Aby to zrobić, uŜyj opcji list_display, która jest krotką zawierającą nazwy pól do wyświetlenia jako kolumny na stronie z listą sond:
class PollAdmin(admin.ModelAdmin): # ... list_display = ('question', 'pub_date')

Dla sprawdzenia jak się sprawuje ta opcja, dodajmy tam naszą metodę was_published_today z pierwszej części tutoriala:
class PollAdmin(admin.ModelAdmin): # ... list_display = ('question', 'pub_date', 'was_published_today')

Teraz nasza strona z listą sond wygląda tak:

MoŜesz kliknąć na nagłówku kaŜdej z kolumn aby posortować listę sond po określonym parametrze — nie dotyczy to kolumny was_published_today, poniewaŜ sortowanie z uŜyciem własnych metod nie jest obsługiwane przez Django. ZauwaŜ teŜ Ŝe nagłówek kolumny dla pola was_published_today jest domyślnie nazwą danej metody (z podkreślnikami zamienionymi na spacje). MoŜna to teŜ zmienić poprzez dodanie atrybutu short_description dla danej metody:
def was_published_today(self): return self.pub_date.date() == datetime.date.today() was_published_today.short_description = 'Published today?'

Teraz dodajmy kolejne usprawnienia do naszej listy: filtry (“Filters”). Dodaj następującą linię do PollAdmin:
list_filter = ['pub_date']

To spowodowało pojawienie się panelu bocznego “Filter” który pozwala na filtrowanie listy sond po polu pub_date:

31

Rodzaj wyświetlanych filtrów zaleŜy od rodzaju pola po którym chcemy filtrować. PoniewaŜ pub_date jest polem typu DateTimeField, Django wie Ŝe potrzebne będą opcje “Any date” (“KaŜda data”), “Today” (“Dzisiaj”), “Past 7 days” (“Ostatnie 7 dni”), “This month” (“Ten miesiąc”), “This year” (“Ten rok”). Zaczyna wyglądać coraz lepiej. Dodajmy moŜliwość wyszukiwania:
search_fields = ['question']

Na górze strony pojawiło się teraz pole wyszukiwarki. Gdy zostanie tam wpisana jakaś fraza, Django przeszuka pola question. MoŜesz uŜyć tylu pól ile potrzebujesz — aczkolwiek pamiętaj, Ŝe Django uŜywa tutaj kwerendy SQL LIKE, więc umieszczaj tu tylko te pola których potrzebujesz. Na koniec, poniewaŜ nasza sonda posiada daty, powinniśmy pogrupować nasze sondy po tym właśnie polu. Dodaj poniŜszą linijkę:
date_hierarchy = 'pub_date'

Teraz na górze strony pojawiły się pola ułatwiające nawigację po dacie. Na samej górze pokazane są dostępne lata. Później miesiące i dni. Pozostało mi jeszcze poinformować Ciebie, Ŝe lista sond jest automatycznie dzielona na strony mieszczące domyślnie do 50 obiektów. Stronicowanie listy sond, pole wyszukiwarki, filtry, grupowanie po datach i sortowanie po kolumnach wspópracują ze sobą tak jak tego oczekujesz.

Upiększanie panelu administracyjnego
Tak naprawdę, napis “Django administration” na górze kaŜdej strony jest nieco mylący. Jest tylko “wypełniaczem”. Bardzo łatwo jest je zmienić korzystając z systemu szablonów Django. Panel administracyjny Django jest tworzony przez samo Django, więc nic dziwnego, Ŝe korzysta ze swojego własnego systemu szablonów. Otwórz swój plik ustawień (mysite/settings.py, pamiętaj) i spójrz na opcję TEMPLATE_DIRS. Jest to krotka, przechowująca ścieŜki do katalogów które Django ma sprawdzać w poszukiwaniu szablonów. Domyślnie TEMPLATE_DIRS jest puste. Dodajmy tam linię aby poinformować Django gdzie ma szukać szablonów:
TEMPLATE_DIRS = ( "/home/my_username/mytemplates", # Change this to your own directory. )

Skopiuj teraz plik admin/base_site.html z domyślnego katalogu szablonów Django (django/contrib/admin/templates) do podkatalogu admin w którymkolwiek z katalogów które ustawiłeś w TEMPLATE_DIRS. Na przykład jeśli umieściłeś w TEMPLATE_DIRS linijkę

32

/home/my_username/mytemplates, jak powyŜej, to skopiuj django/contrib/admin/templates/admin/base_site.html do katalogu /home/my_username/mytemplates/admin/base_site.html. Nie zapomnij podkatalogu admin.

o tym

Teraz wystarczy zmienić skopiowany plik zastępując domyślne teksty Django swoimi. ZauwaŜ, Ŝe kaŜdy domyślny szablon Django moŜe zostać nadpisany. Aby to zrobić, zrób dokładnie to samo co zrobiłeś przed chwilą z base_site.html — skopiuj go z domyślnego katalogu do swojego, i wykonaj zmiany. UwaŜni czytelnicy mogą zapytać: skoro TEMPLATE_DIRS był domyślnie pusty, jak Django wyszukiwał domyślne szablony do panelu administracyjnego ? Odpowiedź: domyślnie, Django automatycznie szuka w podkatalogu templates/ kaŜdej aplikacji. Zajrzyj do loader types documentation (en), Ŝeby dowiedzieć się więcej.

Zmiana wyglądu listy projektów
Kontynuując temat zmian wyglądu, moŜesz takŜe dostosować dla siebie stronę z listą dostępnych aplikacji (indeks) panelu administracyjnego. Domyślnie pokazywane są wszystkie dostępne aplikacje, zgodnie z Twoimi ustawieniami INSTALLED_APPS, w kolejności alfabetycznej. MoŜesz sobie zaŜyczyć konkretnego wyglądu tejŜe strony. Poza tym, indeks jest prawdopodobnie najwaŜniejszą częścią panelu, więc powinien być prosty w uŜyciu. Szablon który tutaj uŜyjemy to admin/index.html (wykonaj te same czynności co przy w poprzedniej sekcji — skopiuj go z katalogu domyślnego do swojego). Następnie otwórz ten plik - zobaczysz Ŝe jest w nim uŜyta zmienna szablonu: app_list. Jest to ten magiczny element, który zwraca listę zainstalowanych aplikacji Django. Zamiast uŜywać tego taga, moŜesz wstawić “na sztywno” odnośniki do konkretnych stron panelu odpowiedzialnych za konkretne obiekty - i ułoŜyć je tak jak uwaŜasz, Ŝe będzie najlepiej.
admin/base_site.html

Aby dowiedzieć się więcej o dostosowywaniu wyglądu panelu administracyjnego Django, zajrzyj na Django admin CSS guide (en). Kiedy juŜ poznasz panel administracyjny Django, przeczytaj trzecią część tego tutoriala aby zacząć tworzyć publicznie widoczną stronę aplikacji.

Pytania/Wsparcie
JeŜeli zauwaŜyłeś błędy w tłumaczeniu dokumentacji proszę zgłoś je nam.

33

Twoja pierwsza aplikacja w Django, część 3
Ta część tutoriala zaczyna się w miejscu, w którym skończyła się część druga. Będziemy kontynuować budowę aplikacji webowej - sondy - i skupimy się na tworzeniu interfejsu uŜytkownika - widokach. ZałoŜenia Widok (ang. view) jest typem strony w Twojej aplikacji Django który generalnie spełnia konkretną funkcję i posiada swój szablon. Na przykład w blogu moŜesz mieć następujące widoki:
• • • • • •

strona główna - wyświetla kilka ostatnich wpisów; strona z wpisem - strona zawierająca kompletny pojedynczy wpis; archiwum, strona roczna - zawiera listę wszystkich miesięcy z wpisami z danego roku; archiwum, strona miesięczna - j.w., ale z listą dni; archiwum, strona jednodniowa - strona z listą wpisów z danego dnia; dodawanie komentarza - pozwala na dodawanie komentarzy przez czytelników.

W naszej sondzie musimy stworzyć cztery widoki:
• • • •

archiwum - zawiera kilka ostatnich sond; strona z sondą - wyświetla samą sondę; wyniki - podgląd wyników danej sondy; głosowanie - pozwala oddać głos w wybranej sondzie.

W Django kaŜdy widok jest realizowany przez funkcję pojedynczą Pythona.

Opracuj schemat adresów (URL)
Pierwszym krokiem do napisania widoków jest opracowanie struktury adresów. Wykonuje się to poprzez stworzenie modułu Pythona, zwanego URLconf. URLconf instruuje Django która napisana przez nas funkcja obsługuje który URL. Kiedy Django dostanie Ŝądanie udostępnienia którejś z podstron, system sprawdza ustawienie zawierające nazwę modułu. Django ładuje ten moduł i szuka zmiennej urlpatterns, która jest listą krotek (tupli) w formacie:

ROOT_URLCONF

(wyraŜenie regularne, nazwa funkcji Pythona [, opcjonalnie słownik])

Django porównuje URL do którego uŜytkownik zaŜądał dostępu z listą wyraŜeń regularnych zaczynając od pierwszego na liście, i kończąc na pierwszym pasującym. Kiedy znajdzie odpowiednie wyraŜenie regularne, wywołuje pasującą funkcję Pythona z referencją do obiektu HTTPRequest jako pierwszym argumentem, wszystkie wychwycone z wyraŜenia regularnego wartości jako argumenty kluczowe, i argumenty z opcjonalnego słownika (trzecia opcja w tupli).

34

Aby dowiedzieć się więcej o HTTPRequest zajrzyj do dokumentacji Ŝądań i odpowiedzi (en) Django. Więcej informacji na temat URFconfs zobacz dokumentację URLconf (en). Kiedy wywołałeś django-admin.py startproject mysite na początku pierwszej części tutoriala, stworzyłeś domyślne ustawienie URLconf w mysite/urls.py. Równocześnie ustawia zmienną ROOT_URLCONF aby wskazywała na plik:
ROOT_URLCONF = 'mysite.urls'

Czas na jakiś przykład. Wyedytuj plik mysite/urls.py Ŝeby zawierał:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^polls/$', 'mysite.polls.views.index'), (r'^polls/(?P<poll_id>\d+)/$', 'mysite.polls.views.detail'), (r'^polls/(?P<poll_id>\d+)/results/$', 'mysite.polls.views.results'), (r'^polls/(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'), )

Warto się temu przyjrzeć. Kiedy ktoś zaŜąda którejś podstrony z Twojego serwisu - na przykład “/polls/23/”, Django załaduje moduł mysite.urls poniewaŜ jest on wskazywany przez ustawienie ROOT_URLCONF. Tam wyszukuje zmienną urlpatterns i przeszukuje ją w poszukiwaniu pasującego wyraŜenia regularnego. Kiedy je znajdzie r'^polls/(?P<poll_id>\d+)/$' - ładuje wskazany moduł lub pakiet: mysite.polls.views.detail. To odpowiada funkcji detail() w mysite/polls/views.py. Na koniec wywołana zostaje znaleziona funkcja detail() w następujący sposób:
detail(request=<HttpRequest object>, poll_id='23')

Paramter poll_id=23 pochodzi z (?P<poll_id>\d+). UŜywając nawiasów wokół wzorca (?P<nazwa>wzorzec) Django “wyłapuje” pasujący tekst do wzorca i przekazuje do wywołania funkcji jako nazwany parametr. Dla przykładu ?P<poll_id> definiuje nazwę, a \d+ jest wzorcem który wpasowuje się w ciąg cyfr (tworzy w tym przypadki liczbę). PoniewaŜ URL patterns są wyraŜeniami regularnymi, tak naprawdę nie ma Ŝadnych ograniczeń z tym co za ich pomocą moŜna uzyskać. I nie ma potrzeby dodawania URL cruft jak na przykład .php - dopóki nie chcesz się wykazać odrobiną humoru, w przypadku którego moŜesz zrobić tak:
(r'^polls/latest\.php$', 'mysite.apps.polls.views.index'),

Ale nie rób tego. To nic nie daje. Zwróć uwagę, Ŝe te wyraŜenie regularne nie przeszukują parametrów GET i POST. Nie przeszukują równieŜ nazwy domeny. Dla przykładu, w zapytaniu na adres http://www.example.com/myapp/, URLconf przeszukuje tylko /myapp/. W zapytaniu o adresie http://www.example.com/myapp/?page=3, przeszukiwanie będzie równieŜ tylko ciąg znaków /myapp/.

35

Jeśli potrzebujesz pomocy w stosowaniu wyraŜeń regularnych, zajrzyj na stronę Wikipedii lub dokumentacji Pythona (en). MoŜesz takŜe zainteresować się fantastyczną ksiąŜką wydawnictwa O’Reilly “Matsering Regular Expressions” autorstwa Jefrrey’a Friedla. Na koniec krótko o wydajności: te wyraŜenia regularne są kompilowane podczas pierwszego załadowania modułu URLconf, dzięki czemu są bardzo szybkie.

Pierwszy widok
Mamy na razie stworzony poprawny URLconf, ale nie mamy jeszcze Ŝadnego widoku. Zanim zaczniemy, trzeba sprawdzić czy Django poprawnie interpretuje nasze ustawienia. Uruchom wbudowany w Django serwer WWW:
python manage.py runserver

Teraz idź do adresu “http://localhost:8000/polls/ w swojej przeglądarce. Powinieneś ujrzeć ładnie sformatowaną stronę błędu z następującym komunikatem:
ViewDoesNotExist at /polls/ Tried index in module mysite.polls.views. Error was: 'module' object has no attribute 'index'

Ten błąd wystąpił poniewaŜ nie stworzyłeś jeszcze funkcji index() w pliku mysite/polls/views.py. Spróbuj takŜe wywołać “/polls/23/”, “/polls/23/results/” i “/polls/23/vote/”. Wyświetlany błąd informuje Cię który widok Django próbował dopasować do danego wywołania (i oczywiście mu się nie udało, poniewaŜ jeszcze nie napisaliśmy Ŝadnego widoku). Czas na napisanie pierwszego widoku. Otwórz plik mysite/polls/views.py i wpisz tam następujący kod:
from django.http import HttpResponse def index(request): return HttpResponse("Hello, world. You're at the poll index.")

To jest najprostszy z moŜliwych widoków. Odwiedź teraz “/polls/” w przeglądarce powinieneś zobaczyć tam powyŜszy tekst. Teraz dodaj tam kolejny widok (funkcje widoku). Wygląda nieco inaczej, poniewaŜ pobiera argument (pamiętaj Ŝe argumenty są wyłapywane za pomocą wyraŜeń regularnych z URLconf):
def detail(request, poll_id): return HttpResponse("You're looking at poll %s." % poll_id)

Zajrzyj ponownie pod adres “/polls/34/”. Wyświetli on jakiekolwiek wpisane przez Ciebie w adresie ID sondy.

36

Piszemy widoki, które coś robią
KaŜdy widok musi wykonać jedną z dwóch akcji: zwrócić obiekt HttpResponse zawierający treść Ŝądanej strony, lub rzucenie wyjątku takiego jak Http404. Reszta jest pozostawiona Tobie. Widok moŜe odczytywać dane z bazy danych, ale nie musi. MoŜesz uŜyć systemu szablonów Django lub teŜ innych. MoŜe generować plik PDF, zwracać XML, stworzyć w locie archiwum ZIP, lub cokolwiek zechcesz, uŜywając jakich chcesz bibliotek. Jedyne czego oczekuje Django, to HttpResponse, lub wyjątek. Ze względu na wygodę, będziemy się posługiwać wbudowanym w Django API dostępu do bazy danych, tak jak robiliśmy to pierwszej części tutoriala. To jest przykładowa implementacja widoku index(), który wyświetla ostatnie 5 pytań (sond) będących w systemie, oddzielone przecinkami w kolejności w jakiej zostały opublikowane:
from mysite.polls.models import Poll from django.http import HttpResponse def index(request): latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5] output = ', '.join([p.question for p in latest_poll_list]) return HttpResponse(output)

Występuje tam jeden problem, mianowicie: wygląd strony jest na sztywno zakodowany w funkcji widoku. Jeśli chciałbyś teraz zmienić wygląd strony, musisz poddać edycji kod widoku. Lepiej jest jednak uŜyć systemu szablonów (ang. templates) Django aby oddzielić logikę aplikacji od jej wyglądu:
from django.template import Context, loader from mysite.polls.models import Poll from django.http import HttpResponse def index(request): latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5] t = loader.get_template('polls/index.html') c = Context({ 'latest_poll_list': latest_poll_list, }) return HttpResponse(t.render(c))

PowyŜszy kod pobiera szablon “polls/index.html” i przypisuje mu wartości. Jako wartości podaje mu słownik mapujący nazwy zmiennych z szablonu na obiekty Pythona. OdświeŜ stronę. Teraz powinieneś ujrzeć błąd:
TemplateDoesNotExist: Your TEMPLATE_DIRS settings is empty. Change it to point to at least one template directory.

No tak, przecieŜ nie mamy jeszcze Ŝadnego szablonu. Najpierw musimy stworzyć katalog, gdzieś w systemie plików, do którego zawartości Django będzie miał dostęp (Django działa z

37

uprawnieniami uŜytkownika który go uruchomił). Nie umieszczaj tego katalogu jako publicznie dostępnego ze względów bezpieczeństwa. Zmień TEMPLATE_DIRS w Twoim pliku ustawień (settings.py) aby poinformować Django gdzie ma szukać szablonów - tak samo jak w drugiej części tutoriala w “upiększanie panelu administracyjnego”. Kiedy juŜ to zrobisz, załóŜ katalog polls w swoim katalogu z szablonami. Następnie stwórz tam plik index.html.ZauwaŜ, Ŝe loader.get_template(``polls/index.html)`` odpowiada plikowi “[katalog szablonów]/polls/index.html” w systemie plików. Wypełnij szablon “polls/index.html”:
{% if latest_poll_list %} <ul> {% for poll in latest_poll_list %} <li>{{ poll.question }}</li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}

OdświeŜ stronę w przeglądarce - powinieneś zobaczyć listę zawierającą jedną pozycję: “What’s up” z części pierwszej tutoriala.

Skrót: render_to_response()
Bardzo częstą wykonywaną czynnością jest załadowanie szablonu, wypełnienie go treścią i zwrócenie obiektu HttpResponse z wyrenderowanym szablonem. Django pozwala uprościć tę procedurę. PoniŜej jest nowa wersje widoku index():
from django.shortcuts import render_to_response from mysite.polls.models import Poll def index(request): latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5] return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})

Zwróć uwagę, Ŝe nie ma potrzeby ładowania modułu loader, Context czy HttpResponse. Funkcja render_to_response() przyjmuje jako argumenty nazwę szablonu (pierwszy z argumentów) oraz słownik jako drugi argument. Zwraca HttpResponse podanego szablonu z uzupełnioną treścią.

Wyjątek 404
Zajmijmy się teraz stroną na której wyświetlana jest sonda. Oto potrzebny widok:
from django.http import Http404 # ... def detail(request, poll_id):

38

try: p = Poll.objects.get(pk=poll_id) except Poll.DoesNotExist: raise Http404 return render_to_response('polls/detail.html', {'poll': p})

Nowością jest tutaj rzucenie wyjątku django.http.Http404 jeŜeli sondy o podanym ID nie ma w bazie danych.

Skrót: get_object_or_404()
Inną często wykonywaną czynnością jest próba pobrania obiektu przy uŜyciu get() i rzucenie wyjątku Http404 jeśli dany obiekt nie istnieje. Django pozwala na skrócenie tej operacji. Oto wersja widoku detail() z uwzględnieniem skrótu:
from django.shortcuts import render_to_response, get_object_or_404 # ... def detail(request, poll_id): p = get_object_or_404(Poll, pk=poll_id) return render_to_response('polls/detail.html', {'poll': p})

Funkcja get_object_or_404() pobiera jako pierwszy argument model Django, a jako drugi - określoną liczbę argumentów kluczowych, które następnie są przekazywane do funkcji get(). Jeśli szukany obiekt nie istnieje, rzuca wyjątek Http404. ZałoŜenia Dlaczego uŜywamy funkcji get_object_or_404() zamiast automatycznie przechwytywać wyjątki DoesNotExist na wyŜszym poziomie, lub teŜ dlaczego nasze API automatycznie nie rzuca wyjątkiem Http404 zamiast DoesNotExist? PoniewaŜ to mieszałoby warstwę modelu z warstwą widoku. Jednym z głównych załoŜeń projektowych Django jest zachowanie luźnych powiązań pomiędzy naleŜącymi do projektu elementami składowymi. Istnieje takŜe funkcja get_list_or_404() która działa podobnie jak get_object_or_404(), z tym wyjątkiem, Ŝe uŜywa filter() zamiast get(). Rzuca wyjątkiem Http404 jeśli lista jest pusta.

Widok 404 (Page not found)
Kiedy zostanie wywołany wyjątek Http404 z jakiegoś widoku, Django ładuje wtedy specjalny widok przeznaczony do obsługi błędu 404. Jest on znajdowany poprzez ustawienie zmiennej handler404 która zawiera łańcuch znakowy w takim samym formacie jakiego uŜywa zmienna URLconf. Sam widok 404 jest zwykłym widokiem, takim jak kaŜdy inny. Zazwyczaj nie będziesz potrzebował samodzielnie pisać tego widoku. Domyślnie, URLconf ma zawartą następującą linię:
from django.conf.urls.defaults import *

39

Zwróć uwagę na ustawienie handler404 w bieŜącym module. Jak widzisz w django/conf/urls/defaults.py, handler404 zawiera domyślnie django.views.defaults.page_not_found. Trzy informacje dotyczące widoku 404:
• •

jest ładowany takŜe wtedy, gdy Django nie udało się przypasować do Ŝadnego wyraŜenia regularnego zawartego w URLconf; jeśli nie zmienisz domyślnego widoku dla wyjątku 404, co zalecamy, cały czas pozostaje Ci do stworzenia szablon dla tego widoku: utwórz plik szablonu o nazwie``404.html`` głównym katalogu szablonów, ten szablon domyślnie zostanie uŜyty do obsługi wszystkich błędów 404; jeŜeli masz w swoich ustawieniach DEBUG ustawione na True, wtedy widok 404 nigdy nie będzie uŜywany, tylko zamiast niego zostanie wyświetlony ślad błędu.

Widok 500 (server error)
Podobnie jak w poprzednim punkcie, w URLconf moŜesz ustawić zmienną handler500 która wskazuje na widok który naleŜy wywołać w przypadku błędów serwera. Błąd “Server error” zdarza się gdy są jakieś błędy w kodzie uniemoŜliwiające jego uruchomienie.

UŜywanie szablonów
Wróćmy do widoku detail() w naszej aplikacji. Jeśli przekaŜemy wartość poll do kontekstu nasz szablon (ang. template) moŜe wyglądać tak:
<h1>{{ poll.question }}</h1> <ul> {% for choice in poll.choice_set.all %} <li>{{ choice.choice }}</li> {% endfor %} </ul>

System szablonów uŜywa składni “kropkowej” w stylu Pythona aby uzyskać dostęp do zmiennych. W przykładzie {{ poll.question }} Django przeszukuje słownik obiektu poll. Gdy to się nie powiedzie, wyszukuje atrybuty - co w tym przypadku zakończy się powodzeniem. Jeśli atrybut nie zostałby znaleziony, Django spróbowałby wywołać metodę question() w tym obiekcie. Wywoływanie metod działa w pętli {% for %}: poll.choice_set.all jest interpretowane jako kod Pythona poll.choice_set.all(), który zwraca listę obiektów Choice i jest odpowiednie dla iteracji w tagu {% for %}. Zajrzyj do przewodnika po szablonach (en) jeśli chcesz uzyskać więcej informacji o szablonach.

Upraszczanie URLconfa

40

Pobaw się przez jakiś czas widokami wraz z systemem szablonów. Gdy edytujesz URLconf, moŜesz zauwaŜyć Ŝe sporo części się w nim powtarza:
urlpatterns = patterns('', (r'^polls/$', 'mysite.polls.views.index'), (r'^polls/(?P<poll_id>\d+)/$', 'mysite.polls.views.detail'), (r'^polls/(?P<poll_id>\d+)/results/$', 'mysite.polls.views.results'), (r'^polls/(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'), )

Na przykład część mysite.polls.views jest w kaŜdym odwołaniu. PoniewaŜ jest to dość częsty przypadek, szkielet URLconf dostarcza sposobu na skrócenie przedrostków. MoŜesz usunąć wszystkie przedrostki i wstawić je jako pierwszy argument do patterns():
urlpatterns = patterns('mysite.polls.views', (r'^polls/$', 'index'), (r'^polls/(?P<poll_id>\d+)/$', 'detail'), (r'^polls/(?P<poll_id>\d+)/results/$', 'results'), (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'), )

PowyŜszy zapis funkcjonalnie jest identyczny z poprzednim, ale jest znacznie krótszy i czytelniejszy.

Dzielenie URLconfs
Skoro juŜ przy tym jesteśmy, powinniśmy teraz rozdzielić adresy naszej sondy od konfiguracji całego projektu. Aplikacje Django powinny być rozdzielne - powinna być moŜliwość przeniesienia kaŜdej z nich do innej instalacji Django przy minimalnym nakładzie sił. Nasza sonda jest jak na razie ładnie oddzielona od samego projektu dzięki ścisłej strukturze katalogów która została utworzona przez python manage.py startapp, ale jedna jej część jest ustawiana razem z innymi ustawieniami Django: URLconf. Konfigurowaliśmy ustawienia adresów w mysite/urls.py, ale adresy przygotowane dla aplikacji są specyficzne dla tej właśnie aplikacji, a nie dla całego projektu - dlatego przenieśmy je do katalogu aplikacji. Skopiuj plik mysite/urls.py do mysite/polls/urls.py`. Teraz z ``mysite/urls.py usuń wszystkie adresy specyficzne dla sondy i wstaw tam wywołanie include():
(r'^polls/', include('mysite.polls.urls')),

Funkcja include() zwraca zawartość innego URLconfa. ZauwaŜ Ŝe wyraŜenia regularne nie posiadają kończącego $ (znak końca linii) ale posiada kończący ukośnik. Kiedy Django napotyka wywołanie include(), usuwa pasującą część adresu i przekazuje pozostałą część do dołączanego instrukcją include() URLconfa. Oto co się dzieje gdy uŜytkownik wywoła adres /polls/34/: 41

• • •

Django znajdzie pasujące '^polls/' usunie z wywołania pasujący tekst przekaŜe pozostały tekst (34/) do URLconfa ‘mysite.polls.urls’ w celu dalszego przetworzenia.

Teraz, kiedy juŜ mamy to rozłączone, musimy uprościć URLconf ‘mysite.polls.urls’ poprzez usunięcie początkowego “polls/” z kaŜdej linii:
urlpatterns = patterns('mysite.polls.views', (r'^$', 'index'), (r'^(?P<poll_id>\d+)/$', 'detail'), (r'^(?P<poll_id>\d+)/results/$', 'results'), (r'^(?P<poll_id>\d+)/vote/$', 'vote'), )

Ideą stojącą za stworzeniem funkcji include() oraz rozbiciem URLconfa było ułatwienie łączenia róŜnych aplikacji w całość. Teraz, kiedy sonda ma swojego własnego URLconfa, moŜemy ją łatwo umieścić w katalogu “/polls/”, lub “/polls_fun/”, “/content/polls/”, lub jakikolwiek innym, a nasza aplikacja ciągle będzie działać. Wszystkie aplikacje muszą się zajmować swoimi relatywnymi URLami, nie absolutnymi. Kiedy juŜ będziesz dobrze orientował się w temacie tworzenia widoków, przeczytaj czwartą część tutoriala aby nauczyć się tworzenia prostych formularzy oraz ogólnych widoków (generic view).

Pytania/Wsparcie
JeŜeli zauwaŜyłeś błędy w tłumaczeniu dokumentacji proszę zgłoś je nam.

42

Twoja pierwsza aplikacja w Django, część 4
Ten tutorial zaczyna się tam, gdzie kończy się tutorial 3. Kontynuujemy tworzenie aplikacji ankiety, w tej części skupimy się na prostym przetwarzaniu formularzy oraz upraszczaniu naszego kodu.

Piszemy prosty formularz
Uaktualnijmy nasz szablon zawierający szczegóły ankiety (“polls/detail.html”) z poprzedniego tutoriala, tak, aby szablon zawierał znacznik HTML <form>:
<h1>{{ poll.question }}</h1> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} <form action="/polls/{{ poll.id }}/vote/" method="post"> {% for choice in poll.choice_set.all %} <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> <label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br /> {% endfor %} <input type="submit" value="Głosuj" /> </form>

Szybkie wyjaśnienie:

PowyŜszy szablon wyświetla przycisk typu "radio" dla kaŜdego wyboru ankiety. Pole value dla kaŜdego przycisku opcji jest skojarzone z ID obiektu choice. Atrybut name kaŜdego przycisku opcji jest dostępny w "choice". To oznacza, Ŝe jeśli ktoś wybiera jeden z przycisków i wysyła formularz form, to przeglądarka otrzyma metodą POST dane o zawartości choice=3. Ustawiliśmy atrybut formularza action na /polls/{{ poll.id }}/vote/ oraz method na "post". UŜywanie method="post" (zamiast method="get") jest bardzo waŜne, poniewaŜ wysyłanie formularza zmieni dane po stronie serwera. JeŜeli kiedykolwiek tworzysz formularz, który zmienia dane po stronie serwera, uŜywaj method="post". Ta wskazówka nie ma nic wspólnego z Django, jest to dobra praktyka tworzenia aplikacji internetowych. forloop.counter oznacza ile razy znacznik for wykonał kod wewnątrz pętli. Więcej informacji znajdziesz w dokumentacji dla znacznika “for”.

Teraz utwórzmy widok Django, który obsługuje wysłane dane oraz coś z nimi robi. Pamiętaj, Ŝe w tutorialu nr 3, utworzyliśmy URLconf dla aplikacji pools, zawierający linie:
(r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),

Utwórzmy więc funkcję vote() w mysite/polls/views.py:

43

from django.shortcuts import get_object_or_404, render_to_response from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse from mysite.polls.models import Choice, Poll # ... def vote(request, poll_id): p = get_object_or_404(Poll, pk=poll_id) try: selected_choice = p.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): # Pokaz ponownie formularz do glosowania. return render_to_response('polls/detail.html', { 'poll': p, 'error_message': "Nie wybrales zadnej opcji", }) else: selected_choice.votes += 1 selected_choice.save() # Zawsze zwróć HttpResponseRedirect po udanym obsłuŜeniu danych z POST. # To zapewnia, Ŝe dane nie zostaną wysłane dwa razy, jeŜeli uŜytkownik # kliknie w przeglądarce przycisk Wstecz . return HttpResponseRedirect(reverse('mysite.polls.views.results', args=(p.id,)))

Ten kod zawiera kilka rzeczy, o których jeszcze nie mówiliśmy w tym tutorialu:

jest obiektem przypominającym słownik, który pozwala na dostęp do otrzymanych danych po nazwie klucza. W tym przypadku request.POST['choice'] zwraca (jako tekst) ID wybranej opcji ankiety. Wartości z request.POST są zawsze tekstem (obiektami string).
request.POST

Django dostarcza równieŜ request.GET do pobierania w ten sam sposób danych z metody GET. W naszym kodzie uŜywamy jednak request.POST, aby upewnić się, Ŝe dane będą zmieniane tylko przez wywołanie POST.
• request.POST['choice'] zgłosi wyjątek KeyError, jeŜeli choice nie był dostarczony w danych metody POST. PowyŜszy kod oczekuje wyjątku KeyError oraz wyświetla ponownie formularz ankiety z informacją o błędzie, jeŜeli choice nie był podany. Po zwiększeniu liczby głosów (selected_choice.votes += 1), kod zwraca HttpResponseRedirect zamiast zwykłego HttpResponse. HttpResponseRedirect przyjmuje pojedynczy argument: adres URL, do którego uŜytkownik zostanie przekierowany (zobacz kolejny punkt, jak tworzymy w tym przypadku adres URL). Zgodnie z komentarzem w kodzie, po udanym obsłuŜeniu danych z POST powinieneś zawsze zwracać obiekt HttpResponseRedirect. To nie jest specyficzne dla Django; to po prostu dobra praktyka przy tworzeniu aplikacji internetowych. UŜywamy funkcji reverse() w przekierowaniu HttpResponseRedirect. Ta funkcja pomaga uniknąć sztywnego wpisywania adresu URL w funkcji widoku. Jako parametr przekazujemy nazwę widoku, który obsłuŜy zapytanie oraz zmienne, które są uŜyte w tym adresie URL i wskazują na ten widok. W tym przypadku, uŜywając URLConf, który ustawiliśmy w tutorialu 3, wywołanie reverse() zwróci tekst podobny do tego: '/polls/3/results/'

44

… gdzie 3 jest wartością p.id. Ten przekierowany URL wtedy wywoła widok 'results', który wyświetli końcową stronę. Zwróć uwagę, Ŝe musisz tutaj uŜyć pełnej nazwy widoku (łącznie z prefiksem). Więcej informacji o reverse() moŜesz znaleźć w dokumentacji URL dispatchera. Jak wspomniano w tutorialu 3, request jest obiektem HTTPRequest. Więcej o obiektach HTTPRequest znajdziesz w dokumentacji request and response. Po tym, jak ktoś zagłosuje w ankiecie, widok vote() przekierowuje do strony z wynikami ankiety. Napiszmy widok:
def results(request, poll_id): p = get_object_or_404(Poll, pk=poll_id) return render_to_response('polls/results.html', {'poll': p})

To prawie to samo co widok detail() z tutoriala nr 3. Jedyną róŜnicą jest nazwa szablonu. Poprawimy ten zbyteczny kod później. Utwórzmy szablon results.html:
<h1>{{ poll.question }}</h1> <ul> {% for choice in poll.choice_set.all %} <li> {{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }} </li> {% endfor %} </ul>

Teraz otwórz /polls/1/ w przeglądarce i zagłosuj w ankiecie. Powinieneś zobaczyć stronę z wynikami, która jest uaktualniana za kaŜdym razem, jak głosujesz. JeŜeli wysyłasz formularz bez wyboru na co głosujesz, powinieneś zobaczyć informacje o błędzie.

UŜyj widoków generycznych - im mniej kodu tym lepiej
Widoki detail() (z tutoriala nr 3) oraz results() są wręcz niemiłosiernie proste — i jak wspomniano wcześniej — zbyteczne. Widok index() (takŜe z tutoriala nr 3), który wyświetla listę ankiet, jest podobny. Te widoki wykonują często powtarzane czynności w aplikacji WWW: pobranie danych z bazy danych zgodnie z parametrem przekazanym w adresie URL, załadowanie szablonu oraz zwrócenie przetworzonego szablonu. PoniewaŜ jest to tak często wykonywane, Django dostarcza skrót nazywany systemem “widoków generycznych”. Widoki generyczne są abstrakcją do punktu, w którym nie musisz nawet pisać kodu w Pythonie, aby napisać aplikację.

45

Przeróbmy teraz naszą aplikację ankiet, aby uŜywała systemu widoków generycznych. MoŜemy więc skasować trochę kodu, który napisaliśmy wcześniej. Musimy tylko wykonać kilka kroków, aby dokonać tej konwersji. Dlaczego zmieniamy kod w ten sposób? Ogólnie, gdy piszesz aplikacje w Django, musisz ocenić czy widoki generyczne są dobrym rozwiązaniem Twojego problemu. JeŜeli tak, to będziesz ich uŜywać od samego początku zamiast zmieniać kod na końcu pisania aplikacji. Jednak w tym tutorialu celowo skupiamy się na pisaniu widoków od podstaw, aby pokazać podstawową koncepcje. Powinieneś znać podstawy matematyki, aby móc korzystać z kalkulatora. Otwórz plik ustawień adresów URL polls/urls.py. Wygląda mniej więcej tak, zgodnie z tym, co napisaliśmy do tej pory:
from django.conf.urls.defaults import * urlpatterns = patterns('mysite.polls.views', (r'^$', 'index'), (r'^(?P<poll_id>\d+)/$', 'detail'), (r'^(?P<poll_id>\d+)/results/$', 'results'), (r'^(?P<poll_id>\d+)/vote/$', 'vote'), )

Zmień go, aby wyglądał następująco:
from django.conf.urls.defaults import * from mysite.polls.models import Poll info_dict = { 'queryset': Poll.objects.all(), } urlpatterns = patterns('', (r'^$', 'django.views.generic.list_detail.object_list', info_dict), (r'^(?P<object_id>\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict), url(r'^(?P<object_id>\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html'), 'poll_results'), (r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'), )

UŜywamy tutaj dwóch widoków generycznych: object_list oraz object_detail. Te dwa widoki są abstrakcją koncepcji “wyświetl listę obiektów” oraz “wyświetl stronę ze szczegółami dla konkretnego typu obiektu”.

KaŜdy widok generyczny musi wiedzieć na jakich danych będzie działać. Te dane podaje się w słowniku. Klucz queryset w tym słowniku wskazuje na listę obiektów, które będą obsługiwane przez generyczny widok.

46

Widok generyczny object_detail oczekuje wartości ID przekazanej z adresu URL, która nazywa się "object_id", wiec zmieniliśmy poll_id na object_id dla widoków generycznych. Dodaliśmy nazwę poll_results do widoku wyników, aby mieć moŜliwość odwołania się do jego adresu URLa w późniejszym czasie (zobacz dokumentację na temat konfigurowania wzorców adresów URL, aby uzyskać więcej informacji).

UŜywamy tutaj takŜe funkcji url() z pakietu django.conf.urls.defaults. Jest to dobry zwyczaj, aby uŜywać url() kiedy podaje się wzorzec taki, jak tutaj. Domyślnie, widok generyczny object_detail uŜywa szablonu nazywającego się <nazwa aplikacji>/<nazwa modelu>_detail.html. W naszym przypadku, uŜywa szablonu "polls/poll_detail.html". Zmień nazwę szablonu polls/detail.html na polls/poll_detail.html oraz zmień wiersz render_to_response() w vote(). Podobnie, widok generyczny object_list uŜywa szablonu nazwywającego się <nazwa aplikacji>/<nazwa modelu>_list.html. Zmień więc polls/index.html na polls/poll_list.html. PoniewaŜ mamy więcej niŜ jeden wpis w URLconf, który uŜywa object_detail dla aplikacji polls, określamy ręcznie nazwę szablonu dla widoku wyników: template_name='polls/results.html'. W przeciwnym razie obydwa widoki uŜywałyby tego samego szablonu. ZauwaŜ, Ŝe uŜywamy dict(), aby zwrócić w tym miejscu zmieniony słownik. Note
all()

jest leniwe

To moŜe wyglądać trochę przeraŜająco: wywołanie Poll.objects.all() w widoku szczegółu, który tylko potrzebuje jednego obiektu Poll, ale nie martw się; Poll.objects.all() jest właściwie specjalnym obiektem nazywanym QuerySet, który jest “leniwy” i nie wyciąga nic z bazy danych, dopóki nie musi. W czasie, gdy wystąpi zapytanie do bazy, widok generyczny object_detail będzie miał swój zasięg zmniejszony do pojedynczego obiektu, więc ewentualne zapytanie wybierze z bazy danych tylko jeden wiersz. JeŜeli chciałbyś się dowiedzieć, jak to działa, zajrzyj do dokumentacji Django na temat API bazy danych, która wyjaśnia leniwą naturę obiektów QuerySet. W poprzednich częściach tego tutoriala, szablony miały podany kontekst, który zawierał zmienne poll oraz latest_poll_list. Jednak widoki generyczne dostarczają zmienne object oraz object_list jako kontekst. Dlatego musisz zmienić szablony, aby zawierały nowe zmienne kontekstu. Przejrzyj szablony i zmodyfikuj kaŜde odniesienie do latest_poll_list na object_list. Zmień teŜ kaŜde wystąpienie poll na object. MoŜesz teraz usunąć widoki index(), detail() oraz results() z polls/views.py. JuŜ ich nie potrzebujemy — zostały zastąpione przez widoki generyczne.

47

Widok vote() jest jednak ciągle potrzebny. Musi być jednak zmodyfikowany, aby odpowiadał nowemu kontekstowi zmiennych. W wywołaniu render_to_response(), zmień nazwę zmiennej poll na object. Ostania rzecz do zrobienia to naprawa obsługi adresów URL z uwzględnieniem uŜycia widoków generycznych. W widoku vote powyŜej uŜyliśmy funkcji reverse(), aby uniknąć sztywnego wpisywania adresów URL w widokach. Teraz przełączyliśmy się na widok generyczny, więc musimy zmienić wywołanie reverse(), aby wskazywało z powrotem do naszego widoku generycznego. Nie moŜemy juŜ po prostu uŜyć funkcji widoku — widoki generyczne mogą (i są) uŜywane wielokrotnie — ale moŜemy uŜyć nazwy, której uŜyliśmy:
return HttpResponseRedirect(reverse('poll_results', args=(p.id,)))

Uruchom teraz serwer i uŜyj nowej aplikacji ankiet opartej o widoki generyczne. Aby dowiedzieć się więcej o widokach generycznych, zobacz dokumentację widoków generycznych.

JuŜ wkrótce
Ten tutorial kończy się w tym momencie. Ale sięgnij teŜ po inne informacje:
• • • • • •

Zaawansowane przetwarzanie formularzy UŜywanie framework’a RSS UŜywanie framework’a cache’owania UŜywanie framework’a komentarzy Zaawansowane funkcje admina: uprawnienia Zaawansowane funkcje admina: Własny JavaScript

W międzyczasie moŜesz przeczytać resztę dokumentacji Django i zacząć pisać własne aplikacje.

Pytania/Wsparcie
JeŜeli zauwaŜyłeś błędy w tłumaczeniu dokumentacji proszę zgłoś je nam.

48

Django FAQ
Pytania ogólne
Dlaczego ten projekt istnieje?
Django powstało w odpowedzi na konkretny problem: World Online, dział WWW gazety w Lawrence, jest odpowiedzialny za intensywne tworzenie aplikacji internetowych z dziennikarskimi terminami. W szybko zmieniającym sie środowisku prasowym, World Online ma niekiedy tylko kilka godzin na wykonanie skomplikowanej aplikacji internetowej, licząc od koncepcji do publicznego uruchomienia. Jednocześnie deweloperzy World Online zawsze byli perfekcjonistami, jeŜeli chodzi o najlepsze praktyki tworzenia aplikacji internetowych. Pod koniec 2003 roku deweloperzy World Online (Adrian Holovaty i Simon Willison) zerwali z PHP i zaczęli uŜywać Pythona do rozwijania serwisów internetowych. Podczas intensywnego tworzenia bogatych, interaktywnych serwisów, takich jak Lawrence.com, zaczęli wydobywać wspólne elementy tworzenia serwisów internetowych, które pozwoliły im coraz szybciej budować aplikacje. Stale ulepszali ten framework, dodając coraz to nowe funkcje. Latem 2005 roku firma World Online zdecydowała się na publiczne udostępnienie powstałego oprogramowania jako Django. PoniewaŜ stworzenie Django nie byłoby moŜliwe bez całej masy projektów wolnego oprogramowania — Apache, Python, PostgreSQL oraz jeszcze kilku innych — byli zachwyceni, Ŝe mogą odwdzięczyć sie tym społeczności wolnego oprogramowania.

Co oznacza “Django” i jak się to wymawia?
Nazwa Django pochodzi od Django Reinhardt, cygańskiego gitarzysty jazzowego z lat 19301950. Do dnia dzisiejszego jest uwaŜany za jednego z najlepszych gitarzystów wszechczasów. Posłuchaj tej muzyki, a spodoba Ci się. Django wymawiamy JANG-oh, rym z FANG-oh. D jest tutaj nieme (tak wymawiają Amerykanie). Udostępniamy takŜe nagranie audio przedstawiające wymowę.

Czy Django jest stabilne?
Tak. Firma World Online uŜywa Django od więcej niŜ trzech lat. Serwisy budowane na Django bez większych problemów wytrzymują ruch na poziomie jednego miliona wyświetleń na godzinę, a nawet więcej. Tak, jest całkiem stabilne.

Czy Django jest skalowalne?

49

Tak. W porównaniu do całkowitego kosztu budowy aplikacji internetowej, sprzęt jest dość tani. Dlatego teŜ Django jest tak zaprojektowane, aby maksymalnie wykorzystać środowisko sprzętowe w którym będzie pracować. Django wykorzystuje architekturę “shared-nothing”, co oznacza moŜliwość dodawania sprzętu na dowolnym poziomie — serwery baz danych, serwery cache oraz serwery WWW. Framework czysto rozdziela takie komponenty jak warstwa bazy danych i warstwa aplikacji. Dostarcza równieŜ prosty (lecz o ogromnych moŜliwościach) framework cache.

Kto za tym stoi?
Django zostało stworzone w firmie World Online, dziale WWW gazety w Lawrence, Kansas, USA. Adrian Holovaty Adrian jest deweloperem webowym z dziennikarskim doświadczeniem. Był głównym programistą w World Online przed 2,5 roku, czyli w czasie, w którym Django zostało stworzone i wdroŜone na serwisach World Online. Teraz pracuje w washingtonpost.com budując bogate, bazodanowe serwisy informacyjne oraz kontynuuje rozwój Django. Lubi grać na gitarze (w stylu Django Reinhardta) oraz udziela się w pobocznych projektach, takich jak chicagocrime.org. Mieszka w Chicago. Na IRC’u , Adrian jest znany jako adrian_h. Jacob Kaplan-Moss Jacob to zapaleniec z Kalifornii, który podobną ilość czasu spędza na pisaniu kodu i gotowaniu. Jest głównym programistą w World Online, ale aktywnie uczestniczy równieŜ w kilku innych projektach pobocznych. Uczestniczył w tworzeniu dowiązań ObjC dla Pythona i był pierwszą osobą, która wymyśliła, w jaki sposób pisać w Pythonie aplikacje Tivo. W ostatnim czasie stara się uruchomić Pythona na PSP. Mieszka w Lawrence, Kansas, USA. Na IRC’u, Jacob jest znany jako jacobkm. Simon Willison Simon jest szanowanym deweloperem z Angli. Miał roczny staŜ w World Online, podczas którego on oraz Adrian stworzyli Django od podstaw. Jest to najbardziej entuzjastyczny Brytyjczyk jakiego kiedykolwiek byś mógł spotkać, jest pasjonatem najlepszych praktyk tworzenia serwisów internetowych oraz od lat pisze często czytany i znany blog web developerski http://simonwillison.net. Pracuje dla Yahoo w Wielkiej Brytanii, gdzie udało mu się zdobyć tytuł “Hacker Liason.” Mieszka w Londynie. Na IRC’u, Simon jest znany jako SimonW.

50

Wilson Miner Projektowe sztuczki Wilcona sprawiają, Ŝe czujemy się wszyscy jak gwiazdy rocka. Za dnia jest interaktywnym projektantem Apple. Nie pytaj go nad czym pracuje, bo będzie musiał Cię zabić. Mieszka w San Francisco. Na IRC’u, Wilson jest znany jako wilsonian.

Jakie serwisy uŜywają Django?
Strona Wiki Django zawiera ciągle powiększającą się listę serwisów opartych o Django. Śmiało moŜesz dodać tam Twój serwis oparty o Django. Dodatkowo moŜesz przejrzeć serwis DjangoSites., który kolekcjonuje wszystkie serwisy uŜywające Django.

Django wydaje się być framework’iem o wzorcu MCV, ale nazywacie kontroler “widokiem”, widok “szablonem”. Dlaczego nie uŜywacie standardowych nazw?
Podejście do nazw standardowych jest dyskusyjne. W naszej interpretacji wzorca MVC, “widok” opisuje dane, które są prezentowane uŜytkownikowi. To niekoniecznie jak dane wyglądają, ale które dane są prezentowane. Widok opisuje, które dane widzisz, a nie jak je widzisz. To subtelna róŜnica. W naszym przypadku “widok” jest wywołaniem funkcji Pythona przez konkretny URL, dlatego Ŝe wywołanie funkcji opisuje, które dane są prezentowane. Ponadto, uwaŜamy za rozsądne oddzielać zawartość od prezentacji — w tym miejscu dochodzimy do szablonów. W Django “widok” opisuje, które dane są prezentowane, ale widok jest przekierowywany do szablonu, który opisuję jak dane są prezentowane. Gdzie w takim razie jest “kontroler”? W przypadku Django jest to prawdopodobnie sam framework: mechanizm, który wysyła Ŝądanie do odpowiedniego widoku zgodnie z konfiguracją URL’i Django. JeŜeli mielibiśmy stosować skróty, moglibyśmy powiedzieć, Ŝe Django jest frameworkiem “MTV” — czyli “model”, “szablon”, “widok”. Mamy pracę do zrobienia i ostatecznie liczy się efekt — nie waŜne jak rzeczy się nazywają. Django wg nas pozwala, wykonać tą pracę w najbardziej logiczny sposób.

<Framework X> ma <funkcje Y> — Dlaczego nie ma jej w Django?
Jesteśmy świadomi tego, Ŝe na święcie są inne znakomite frameworki. Nie jesteśmy przeciwni zapoŜyczania pomysłów, kiedy uznamy to za stosowne. Jednak Django zostało stworzone dlatego, Ŝe nie byliśmy zadowoleni ze status quo. Tak więc bądź świadom, Ŝe argument typu “poniewaŜ <Framework X> to ma” nie jest wystarczającym powodem na dodanie danej funkcji do Django.

51

Dlaczego napisaliście Django od podstaw zamiast uŜyć gotowych bibliotek Pythona?
Kilka lat temu, na początku powstawania Django, Adrian i Simon spędzili całkiem sporo czasu na rozpoznaniu róŜnych dostępnych Pythonowych frameworków WWW. Niestety Ŝadne z nich nie były dla nas w pełni zadowalające. Jesteśmy wybredni. MoŜesz nawet nas nazwać perfekcjonistami (z terminami). Z czasem natknęliśmy się na biblioteki open-source, wykonujące rzeczy, które juŜ mieliśmy zaimplementowane. ZauwaŜyliśmy, Ŝe inni ludzie rozwiązują podobne problemy w podobny sposób, jednak było juŜ za późno na integrację: mieliśmy juŜ napisane, przetestowane i zaimplementowane własne kawałki fremeworka w kilku ustawieniach produkcyjnych — i nasz kod uroczo spełniał wszystkie wymagania. W wielu przypadkach obserwowaliśmy, Ŝe istniejące frameworki/narzędzia miały pewnego rodzaju fundamentalne wady, które sprawiły, Ŝe staliśmy się wybredni. śadne narzędzie nie zgadzało się w 100% z naszą filozofią. Tak jak wspominaliśmy: jesteśmy wybredni. Udokumentowaliśmy naszą filozofię na stronie filozofii projektowej (en).

Czy Django jest systemem zarządzania treścią (CMS)?
Nie, Django nie jest CMS’em, ani Ŝadnym tego typu produktem. To framework webowy; narzędzie programistyczne, które ułatwia budowanie serwisów internetowych. Nie m sensu porównywać Django z projektami typu Drupal. Django to narzędzie, za pomocą którego moŜesz stworzyć właśnie systemy takie jak Drupal. Oczywiście, automatyczny panel administracyjny Django jest fantastyczny i oszczędza czas — jest on jednak tylko jednym z modułów Django. Choć w Django wygodnie tworzy się aplikacje typu “CMS”, nie oznacza to, Ŝe nie nadaje się ono do budowania aplikacji “nieCMS” (cokolwiek to oznacza!).

Jak mogę pobrać dokumentacje Django, aby czytać ją offline?
Dokumentacja Django jest dostępna w katalogu docs kaŜdego pakietu Django. Pliki dokumentacji są w formacie ReST (ReStructured Text). KaŜdy plik odpowiada stronie www z oficjalnej dokumentacji. PoniewaŜ dokumentacja jest trzymana w systemie kontroli wersji (en), moŜesz śledzić jej zmiany, tak jakbyś przeglądał zmiany w kodzie. Technicznie rzecz ujmujac, dokumentacja na stronie głównej Django jest generowana z najnowszej wersji deweloperskiej plików ReST. MoŜe się więc okazać, Ŝe treść na głównej

52

stronie Django oferuje więcej informacji niŜ wersja dostarczana ze stabilnym pakietem Django.

Gdzie mogę znaleźć programistów Django szukających zleceń?
Sprawdź naszą stronę programiści do zatrudnienia (en), znajdziesz tam całą listę programistów, którzy z radością Ci pomogą.

Pytania instalacyjne
Jak zacząć?
1. 2. 3. 4. Pobierz źródła. Zainstaluj Django (przeczytaj poradnik instalacyjny). Wykonaj tutorial. Przeczytaj dokumentację i zadawaj pytania jeśli tylko nie będziesz umiał sobie z czymś poradzić.

Jak mam naprawić błąd “install a later version of setuptools”?
Uruchom skrypt ez_setup.py w dystrybucji Django.

Jakie wymagania ma Django?
Django wymaga Pythona 2.3 lub nowszego. śadna inna biblioteka nie jest wymagana do normalnego uŜywania Django. Dla środowiska rozwojowego — jeŜeli po prostu chcesz poeksperymentować z Django — nie potrzebujesz mieć zainstalowanego dedykowanego serwera WWW; Django dostarcza swój własny “lekki” serwer rozwojowy. Dla środowiska produkcyjnego, zalecamy Apache 2 oraz mod_python. Pamiętaj jednak, Ŝe Django spełnia kreteria określone w specyfikacji WSGI, co oznacza Ŝe moŜesz go uŜywać z róŜnymi platformami serwerowymi. JeŜeli chcesz uŜywać Django z bazą danych, będziesz potrzebował takŜe silnika bazy danych. Polecamy PostgreSQL, poniewaŜ jesteśmy jego fanami, jednak MySQL, SQLite 3 i Oracle są równieŜ wspierane.

Czy coś tracę uŜywając Pythona 2.3 zamiast najnowszego, takiego jak Python 2.5?
Nie. Django samo w sobie gwarantuje Ŝe będzie działać z kaŜdą wersją Pythona od 2.3 i wyŜszych. Oczywiście jeŜeli będziesz uŜywać nowszej wersji Pythona niŜ 2.3, będziesz w stanie skorzystać z nowych moŜliwości języka jakie oferuje nowsza wersja Pythona razem ze zwiększeniem wydajności i pozostałymi optymalizacjami jakie zostały wykonane w samym języku Python. Mimo wszystko framework Django powinien działać tak samo dobrze z Pythonem 2.3 jak i 2.4 czy 2.5.

53

Czy muszę uŜywać mod_python’a?
W prawdzie zalecamy stosowanie mod_pythona na uŜytek produkcyjny, jednak nie musisz go uŜywać, dzięki temu, Ŝe Django korzysta ze specyfikacji WSGI. Django moŜe porozumiewać się z dowolnym serwerem, który wspiera standard WSGI. Inne konfiguracje nie uŜywające mod_python’a to FastCGI, SCGI, AJP, mod_wsgi. Zobacz Jak uŜywać Django z FastCGI, SCGI lub AJP (en) aby uzyskać więcej informacji. Zobacz takŜe stronę Przygotowanie serwera (en) aby poznać inne sposoby wdroŜenia. JeŜeli tylko chcesz się pobawić i przetestować Django na swoim komputerze, uŜyj serwera WWW, który jest dostarczony razem z Django - na pewno się sprawdzi.

Jak zainstalować mod_python na Windows?
• • • •

Dla Python’a 2.4, pobierz build win32 dla mod_pytona dla Pythona 2.4 (en). Dla Python’a 2.4, sprawdź ten poradnik Django na Windows (en). Dla Python’a 2.3, pobierz mod_python’a z http://www.modpython.org/ i przeczytaj Uruchamianie mod_python’a na Apache na Windows2000 (en). Zobacz takŜe to (nie związane z Windowsem) Poradnik jak uruchomić mod_pythona (en).

Czy Django będzie działać na hostingu dzielonym (jak TextDrive lub Dreamhost)?
Zobacz stronę Django - przyjazne hostingi (en).

Czy powinienem uŜywać oficjalnej wersji czy rozwojowej?
Developerzy Django ulepszają Django kaŜdego dnia, są dobrzy w tym co robią i nie publikują nie działającego kodu. My uŜywamy wersji rozwojowej (z repozytorium Subversion) bezpośrednio na naszych serwerach i uwaŜamy, Ŝe jest stabilna. Mając to na myśli, polecamy stosowanie najnowszej wersji rozwojowej, poniewaŜ generalnie zawiera więcej funkcji i mniej usterek niŜ “oficjalne” wydanie.

UŜywanie Django
Dlaczego mam błąd w imporcie DJANGO_SETTINGS_MODULE?
Upewnij się Ŝe:
• • • •

Zmienna środowiskowa DJANGO_SETTINGS_MODULE wskazuje na pełny moduł Pythona (np. “mysite.settings”). Sprawdź czy moduł znajduje się w sys.path (import mysite.settings powinno działać). Sprawdź, czy moduł nie zawiera błędów składni (oczywiste). JeŜeli uŜywasz mod_pythona, ale bez request handlera z Django, musisz obejść błąd mod_python’a związany z uŜywaniem SetEnv; zanim zaimportujesz cokolwiek z Django, musisz wykonać następującą czynność: 54

os.environ.update(req.subprocess_env)

(gdzie req jest obiektem request mod_pythona).

Nie mogę znieść waszego języka szablonów. Czy muszę go uŜywać?
Sądziliśmy Ŝe nasz system szablonów jest najlepszą rzeczą pod słońcem, jednak wiemy, Ŝe wybór języka szablonów jest bliski religii. Nie ma nic w Django, co wymagałoby uŜywania Djangowego systemu szablonów, więc śmiało moŜesz uŜywać kaŜdego innego — wybór naleŜy do Ciebie.

Czy muszę uŜywać waszej warstwy modelu/bazy danych?
Nie. Zupełnie tak jak z systemem szablonów, warstwa modelu/bazy danych jest oddzielona od reszty frameworka. Jedyny wyjątek to: jeŜeli uŜywasz innej biblioteki do obsługi bazy danych, wówczas nie będziesz mógł uŜywać automatycznie generowanego panelu administracyjnego. Panel ten związany jest z warstwą bazy danych Django.

Jak uŜywać pól typu obrazek i plik?
UŜywanie pól FileField lub ImageField w modelu wymaga kilku kroków: 1. W pliku ustawień projektu (settings.py) zdefiniuj MEDIA_ROOT jako pełną ścieŜkę do katalogu, gdzie będziesz chciał, aby Django gromadziło wgrywane na serwer pliki. (Z powodów wydajnościowych pliki te nie są trzymane w bazie danych.) Zdefiniuj MEDIA_URL jako bazowy publiczny URL tego katalogu. Upewnij się, Ŝe ten katalog ma prawa zapisu na serwerze WWW. 2. Dodaj pole FileField lub ImageField do Twojego modelu, upewnij się, Ŝe zdefiniowałeś opcje upload_to, aby Django wiedziało, który pod katalog z MEDIA_ROOT ma uŜyć podczas wgrywania plików na serwer. 3. W bazie danych zostanie zapisana ścieŜka do pliku (relatywna do MEDIA_ROOT). Aby pobrać pełen URL do pliku, moŜesz skorzystać funkcji którą dostarcza Django get_<nazwapola>_url. Na przykład, jeŜeli Twoje pole ImageField nazywa się mug_shot, moŜesz pobrać pełen URL do Twojego obrazka w szablonie za pomocą {{ object.get_mug_shot_url }}.

Bazy danych i modele
Jak mogę zobaczyć rzeczywiste zapytanie SQL podczas działania Django?
Upewnij sie Ŝe ustawienie DEBUG z Django ma wartość True. Następnie (uŜywając shell-a wpisz:
>>> from django.db import connection >>> connection.queries [{'sql': 'SELECT polls_polls.id,polls_polls.question,polls_polls.pub_date FROM polls_polls', 'time': '0.002'}]

55

connection.queries dostępne jest tylko, jeŜeli DEBUG jest równe True. To jest lista słowników w kolejności wywołania zapytania. KaŜdy słownik ma: ``sql`` -- Treść zapytania SQL ``time`` -- Jak długo zajęło wykonanie zapytania, w sekundach. connection.queries

zawiera wszystkie zapytania SQL — INSERT’y, UPDATE’y, SELECT’y, itd. Za kaŜdym razem, gdy Twoja aplikacja wykonuje zapytanie do bazy, zapytanie zostanie zapamiętane.

Czy mogę uŜyć Django z istniejącą bazą danych?
Tak. Zobacz Integracja z istniejącą bazą danych (en).

JeŜeli wprowadzę zmiany do modelu, to jak mogę zrobić update bazy danych?
JeŜeli nie jest dla Ciebie problemem wyczyszczenie danych, to narzędzie manage.py z Twojego projektu ma opcję resetowania SQL dla konkretnej aplikacji:
manage.py reset twoja_aplikacja

To polecenie usuwa wszystkie tabele skojarzone z twoja_aplikacja i tworzy je na nowo. JeŜeli jednak nie chcesz usunąć danych, musisz ręcznie wykonać wyraŜenie ALTER TABLE na Twojej bazie danych. W taki sposób robiliśmy to zawsze, poniewaŜ działanie na danych to delikatna operacja dlatego teŜ w tym przypadku chcieliśmy uniknąć automatyzacji. Trwają prace, aby dodać funkcjonalność częściowej automatyzacji aktualizacji schematu bazy danych (przp. tłum. zainteresuj się narzędziem dbmigration (en) dla Django`).

Czy modele w Django obsługują klucze główne składające się z kilku kolumn?
Nie. Obsługiwane są tylko jednokolumnowe klucze główne. W praktyce to nie jest problem, poniewaŜ nic Cię nie zatrzymuje przed dodaniem innego ograniczenia (uŜywając opcji modelu unique_together lub tworząc ograniczenie bezpośrednio w bazie danych), wymuszając unikalność na tym poziomie. Jednokolumnowe klucze główne są potrzebne, aby interface admina mógł działać; np. musisz w łatwy sposób być w stanie określić obiekt do edycji lub usunięcia.

Jak dodać specyficzne opcje dla bazy danych do wyraŜenia CREATE TABLE, takie jak określenie typu tabeli jako MyISAM?
Staramy się unikać specjalnych przypadków w kodzie Django, aby spełnić wszystkie specyficzne opcje baz danych takie jak typy tabel itd. JeŜeli chciałbyś uŜywać jakichkolwiek z tych opcji, stwórz plik inicjujący dane SQL (en), który zawiera wyraŜenie ALTER TABLE modyfikujące to, co potrzebujesz. Pliki inicjujące są wykonywane na bazie danych po wyraŜeniach CREATE TABLE. Na przykład, jeŜeli uŜywasz MySQL’a i chciałbyś, aby Twoje tabele uŜywały typu MyISAM, stwórz plik inicjujący dane i wstaw tam coś takiego: 56

ALTER TABLE moja_aplikacja_mojatabela ENGINE=MyISAM;

Jak opisano w dokumentacji, pliki inicjujące dane SQL (en), plik SQL moŜe zawierać dowolny kod SQL, tak więc moŜesz dokonać dowolnych zmian, jakich potrzebujesz.

Dlaczego Django ma wycieki pamięci?
Django nie jest znane z wycieków pamięci. JeŜeli zauwaŜysz, Ŝe procesy Django alokują coraz więcej pamięci bez śladu zwalniania jej, sprawdz czy Twoje ustawienie DEBUG ma wartość True. JeŜeli DEBUG ustawione jest na True, wtedy Django zapisuje kaŜde wykonane zapytanie SQL. (Zapytania są zapisane w django.db.connection.queries. Zobacz Jak mogę zobaczyć rzeczywiste zapytanie SQL podczas działania Django?.) Aby naprawić problem, ustaw DEBUG na False. JeŜeli potrzebujesz wyczyścić listę zapytań ręcznie w Twoim kodzie, po prostu wywołaj reset_queries() w taki sposób:
from django import db db.reset_queries()

Panel administracyjny
Nie mogę się zalogować. Kiedy wprowadzam nazwę uŜytkowanika oraz hasło, pojawia się strona logowania bez Ŝadnych błędów.
Login cookie nie został poprawnie ustawiony, poniewaŜ domena cookie wysłana przez Django nie zgadza się z domeną Twojej przeglądarki. Spróbuj dwóch rzeczy:

Ustaw SESSION_COOKIE_DOMAIN w pliku konfiguracyjnym, aby pasowało do Twojej domeny. Na przykład jeŜeli w przeglądarce otwierasz adres “http://www.mojserwis.pl/admin/“, w ustawieniach Twojego projektu powinieneś ustawić SESSION_COOKIE_DOMAIN = 'www.mojserwis.pl'. Niektóre przeglądarki (Firefox?) nie lubią akceptować cookies z domen, które nie mają kropek w środku. JeŜeli uŜywasz panelu administracyjnego na “localhost” lub w innej domenie która nie ma kropek w nazwie, spróbuj uŜyć “localhost.localdomain” lub “127.0.0.1” dla ustawienia SESSION_COOKIE_DOMAIN.

Nie mogę się zalogować. Kiedy wprowadzam nazwę uŜytkownika oraz hasło, pojawia strona logowania, z błędem “Proszę wprowadź poprawną nazwę uŜytkownika i hasło”.
JeŜeli jesteś pewien, Ŝe Twoja nazwa uŜytkownika i hasło są poprawne, upewnij się, Ŝe Twój uŜytkownik ma ustawione is_active oraz is_staff na True. Panel administracyjny pozwala na dostęp tylko uŜytkownikom, którzy mają te dwa pola ustawione na True.

57

Jak mogę zapobiec, aby cache middleware nie cache’ował panelu administracyjnego?
Ustaw CACHE_MIDDLEWARE_ANONYMOUS_ONLY na True. Zobacz dokumentacje cache’u, aby uzyskać więcej informacji.

Jak automatycznie ustawić wartość pola na uŜytkownika, który ostatnio edytował obiekt w adminie?
W tym przypadku, Django nie ma oficjalnego “właściwego” sposobu. Jednak jest to funkcjonalność, o którą prosi wielu ludzi, więc rozwaŜamy jak to zaimplementować. Problem w tym, Ŝe nie chcemy łączyć warstwy modelu z warstwą admina oraz warstwą Ŝądania (aby pobrać aktualnie zalogowanego uŜytkownika. Jest to dość zawiły problem. Jedna osoba znalazła rozwiązanie które nie wymaga zmian w kodzie źródłowym Django (en), miej jednak na uwadze Ŝe jest to nieoficjalne rozwianie i nie ma gwarancji, Ŝe za jakiś czas nie przestanie działać.

Jak ograniczyć dostęp w panelu administracyjnym, aby obiekty mogły być tylko edytowane przez uŜytkowników którzy je stworzyli?
Zobacz odpowiedź na poprzednie pytanie.

Style CSS oraz obrazki pojawiają się w adminie uŜywając serwera developerskiego, ale nie wyświetlają się gdy uŜywam mod_pythona.
Zobacz serwowanie plików admina (en) w dokumencie “Jak uŜywać Django z mod_pythonem”.

Mój “list_filter” zawiera pole ManyToManyField, ale filtr nie jest wyświetlany.
Django nie wyświetla filtra dla pola ManyToManyField jeŜeli są mniej niŜ dwa powiązane obiekty. Na przykład, jeŜeli Twój list_filter zawiera strony, a w Twojej bazie danych jest tylko jedna taka strona, wtedy filtr “Strona” nie zostanie wyświetlony. W tym przypadku filtrowanie po stronach byłoby bezuŜyteczne.

Jak mogę zmienić funkcjonalność panelu administracyjnego?
Masz kilka opcji. JeŜeli chciałbyś zmodyfikować funkcjonalność w formularzu dodawania/zmiany obiektu, moŜesz dodać dodatkowy JavaScript przez parametr js w class Admin w modelu. Parametr ten jest listą URL’i wskazującymi na pliki JavaScript, które zostaną załadowane w formularzu admina jako znacznik <script>. JeŜeli oczekujesz większej elastyczności niŜ po prostu zmieniając automatycznie wygenerowane formularze, moŜesz śmiało napisać własny widok dla admina. Panel

58

administracyjny jest zasilany przez Django, więc moŜesz napisać własne widoki, które integrują się systemem autoryzacji, sprawdzaniem uprawnień oraz cokolwiek innego potrzebujesz. JeŜeli chciałbyś zmienić wygląd interfejsu admina, przeczytaj kolejną opowiedź.

Dynamicznie generowany panel administracyjny jest brzydki! Jak mogę go zmienić?
Nam się podoba, ale jeŜeli się nie zgadzasz, moŜesz zmodyfikować wygląd panelu administracyjnego przez edycje arkusza CSS oraz/lub skojarzone obrazki. Strona jest zbudowana z prostego HTML’a oraz stylów CSS, więc jakiekolwiek zmiany, które chciałbyś wprowadzić, powinny być moŜliwe uŜywając właśnie CSS. Przygotowaliśmy poradnik do CSS’a wykorzystywanego w adminie (en)

Pisanie kodu
Jak mogę zacząć pisać kod do Django?
Dziękujemy Ŝe pytasz! Napisaliśmy cały dokument poświęcony odpowiedzi na te pytanie. Jest zatytułowany Contributing to Django (en).

Wrzuciłem poprawkę błędu w systemie ticet’ów kilka tygodni temu. Dlaczego ignorujecie moją poprawkę?
Nie martw się: Nie ignorujemy Cię! Warto zrozumieć róŜnicę pomiędzy “ticket jest ignorowany” a “ticket nie został jeszcze rozpatrzony”. System ticketów Django zawiera setki otwartych ticketów o róŜnym wpływie na ostateczną funkcjonalność. Deweloperzy Django muszą je przejrzeć i określić ich priorytet. Poza tym, jeŜeli Twoja prośba o daną funkcjonalność nie ma szans na włączenie do Django, nie będziemy jej ignorować — po prostu zamkniemy ticket. Więc jeŜeli Twój ticket jest ciągle otwarty, to nie oznacza, Ŝe Cię ignorujemy, po prostu nie mieliśmy jeszcze czasu, aby mu się przyjrzeć.

59

Sign up to vote on this title
UsefulNot useful