Ostatnia zmiana:
Styczeń 21, 10:52 po południu
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:
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.
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).
(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 site-packages/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
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 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.
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:
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 - 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:
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.
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
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 polls/models.py aby wyglądał tak jak poniżej:
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()
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-do-wielu (many-to-many) i jeden-do-jednego (one-to-one).
Ta mała część kodu modelu dostarcza Django mnóstwa informacji. Z jego pomocą, Django może:
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:
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.
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:
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>]
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):
# ...
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?>
# 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.
Jeżeli zauważyłeś błędy w tłumaczeniu dokumentacji proszę zgłoś je nam.