Zacznij przygodę z Django

Django to kompletny framework do tworzenia aplikacji internetowych napisany w Pythonie. Główne zalety Django to automatycznie generowany panel admina wraz z systemem użytkowników i uprawnień, obsługa projektów i aplikacji, abstrakcyjna obsługa baz danych (ORM) i wiele innych.
Niniejszy artykuł prezentuje Django na przykładzie prostej aplikacji. Zastosowane w kodzie rozwiązania opisane są w odpowiednich artykułach.

Instalacja

Ostatnią wydaną wersją django jest wersja 0.96.*, lecz można również użyć bieżącej wersji z SVN zawierającą więcej zmian i usprawnień. By pobrać bieżącą wersję z repozytorium musimy mieć zainstalowane subversion, następnie jako zwykły użytkownik wykonujemy polecenie:
svn co http://code.djangoproject.com/svn/django/trunk/ django_src
Co pobierze bieżący kod django. By zainstalować zarówno Django 0.96 jak i wersję z SVN jako root wykonujemy:
cd django_src
python setup.py install
Gdzie django_src to nazwa katalogu z pobranym kodem django (inna nazwa w przypadku pobranego django 0.96). Warto co jakiś czas aktualizować django pobrane z SVN. Wystarczy że stworzymy symlinka między katalogiem django_src/django a /usr/lib/pythonWERSJA/site-packages/django/. Przykładowe polecenie (jako root):
ln -s /ścieżka/do/django_src/django /usr/lib/python2.4/site-packages/django
Teraz wystarczy pobrać nową wersję z svn a django na naszym komputerze "automatycznie" zostanie zaktualizowany.

Różnice między Django 0.96 a Django-SVN/Django-1.0

Pomiędzy tymi wersjami Django istnieje wiele wstecznie niezgodnych różnic. Nowe, dopiero tworzone projekty powinny być pisane pod wersją rozwojową, która niebawem zmieni się w wersję 1.0. W porównaniu do wersji 0.96 zmianie uległ m.in. komponent obsługujący formularze, a z nim konfiguracja modeli dla Panelu Admina. Listę wstecznie niezgodnych zmian wprowadzonych po wydaniu wersji 0.96 znajdziemy na wiki projektu.

Dodatkowe zależności

  • Do obsługi SQLite django używa pysqlite
  • Postgres: psycopg
  • MySQL: mysql-python

Tworzenie aplikacji w django

Tworzenie projektu

Projekt składa się z aplikacji, np. CMS z różnych modułów. By stworzyć projekt wystarczy wydać polecenie:
django-admin.py startproject NAZWA_PROJEKTU
django-admin.py startproject blog
Stworzone zostaną podstawowe pliki projektu, możemy nawet uruchomić serwer django dla tego projektu.

Uruchamianie serwera django

Po przejściu do katalogu projektu wykonaj:
python manage.py runserver 8080
To polecenie uruchomi serwer django. Pod adresem http://localhost:8080/ dostępny będzie nasz serwis django.
django1


Konfiguracja projektu - bazy danych

Django jest silnie powiązane z bazami danych i do dalszych operacji będzie nam potrzebna dostępna baza danych (sqlite3, mysql lub postgresql). Edytujemy settings.py
DATABASE_ENGINE = ''           # 'postgresql', 'mysql', 'sqlite3' lub 'ado_mssql'.
DATABASE_NAME = ''             # nazwa bazy danych lub ścieżka dla bazy sqlite3
DATABASE_USER = ''             # użytkownik bazy, puste dla sqlite3
DATABASE_PASSWORD = ''         # hasło użytkownika, puste dla sqlite3
DATABASE_HOST = ''             # host do bazy danych, puste localhost
DATABASE_PORT = ''             # Podaj port jeżeli niestandardowy, puste dla sqlite3.
Przykładowo użyjemy:
DATABASE_ENGINE = 'sqlite3'           # 'postgresql', 'mysql', 'sqlite3' lub 'ado_mssql'.
DATABASE_NAME = 'bazka.db'             # nazwa bazy danych lub ścieżka dla bazy sqlite3
DATABASE_USER = ''             # użytkownik bazy, puste dla sqlite3
DATABASE_PASSWORD = ''         # hasło użytkownika, puste dla sqlite3
DATABASE_HOST = ''             # host do bazy danych, puste localhost
DATABASE_PORT = ''             # Podaj port jeżeli niestandardowy, puste dla sqlite3.
Następnie zatrzymujemy serwer django i synchronizujemy bazę danych. Z innych ustawień możemy zmienić język i strefę czasową:
TIME_ZONE = 'Europe/Warsaw'
LANGUAGE_CODE = 'pl'

Aktualizacja bazy danych

Po dodaniu nowej aplikacji czy po podaniu danych do bazy danych nowego projektu musimy zsynchronizować dane w bazie danych. Służy do tego polecenie:
python manage.py syncdb
W przypadku rozpoczynania pracy z bazą danych django zapyta nas też o dane głównego admina projektu:
piotr@localhost ~/tutorialProjekt $ python manage.py syncdb
Creating table auth_message
Creating table auth_group
Creating table auth_user
Creating table auth_permission
Creating many-to-many tables for Group model
Creating many-to-many tables for User model
Creating table django_content_type
Creating table django_session
Creating table django_site

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (Leave blank to use 'piotr'):
E-mail address: 1@1.pl
Password:
Password (again):
Superuser created successfully.
Adding permission 'group | Can add group'
Adding permission 'group | Can change group'
Adding permission 'group | Can delete group'
Adding permission 'user | Can add user'
Adding permission 'user | Can change user'
Adding permission 'user | Can delete user'
Creating example.com Site object
Adding permission 'site | Can add site'
Adding permission 'site | Can change site'
Adding permission 'site | Can delete site'
Gdy pojawi się pytanie Would you like to create one now? (yes/no): podajemy "yes" i potem podajemy login i hasło.

Tworzenie aplikacji

By stworzyć aplikację wystarczy wykonać polecenie z katalogu projektu:
python manage.py startapp NAZWA_APLIKACJI
python manage.py startapp news
Co stworzy katalog aplikacji z plikami:
news/
    __init__.py
    models.py
    views.py

models.py zawiera modele naszej aplikacji. Podstawa to struktura tabel. Oto zawartość pliku dla naszego tutoriala:
from django.db import models

class News(models.Model):
	title = models.CharField(max_length=255, verbose_name='Tytuł')
	text = models.TextField(verbose_name='Treść')
	date = models.DateTimeField(verbose_name='Data dodania')
	class Meta:
		verbose_name = "Wiadomość"
		verbose_name_plural = "Wiadomości"
	class Admin:
		list_display = ('title', 'date')
		list_filter = ['date']
		search_fields = ['title', 'text']
		date_hierarchy = 'date'
	def __str__(self):
		return self.title
Każdy model to klasa opisująca strukturę tabeli w bazie danych. Pole CharField i TextField służą do przechowywania tekstu, DateTimeField - daty. Budowę modeli poznamy w kolejnym artykule. Po zapisaniu edytujemy settings.py projektu. Do INSTALLED_APPS dodajemy naszą aplikacje (NAZWA_PROJEKTU.NAZWA_APLIKACJI) czyli 'blog.news'. Zapisujemy i synchronizujemy bazę danych. Powinniśmy zobaczyć:
Creating table news

Panel Admina

By "włączyć" panel admina wykonujemy:
  • do INSTALLED_APPS w settings.py dodajemy 'django.contrib.admin'
  • synchronizujemy bazę danych
  • edytujemy urls.py i usuwamy komentarz (#) z wiersza:
(r'^admin/', include('django.contrib.admin.urls')),
Panel Admina dostępny jest pod adresem http://localhost:8080/admin/
django2
django3
django4

Interfejs użytkownika

Mamy gotowy panel administratora wiadomości lecz nie mamy jeszcze interfejsu od strony użytkownika. Zaczynamy od zaprojektowania URLi. urls.py zawierają listę powiązanych adresów URL z akcjami wywoływanymi w przypadku dopasowania URLa. Format:
(wyrażenie regularne, funkcja pythona do wykonania [, opcjonalnie katalog])
urls.py powinien wyglądać tak:
from django.conf.urls.defaults import *
from blog.news.models import *

urlpatterns = patterns('',
	(r'^admin/', include('django.contrib.admin.urls')),
	(r'^/?$', 'django.views.generic.list_detail.object_list', {'queryset':News.objects.all().order_by('-id'), 'paginate_by':10, 'allow_empty':True, 'template_name':'list.html'}),
	(r'^/(?P<page>[0-9]+)$', 'django.views.generic.list_detail.object_list', {'queryset':News.objects.all().order_by('-id'), 'paginate_by':10, 'allow_empty':True, 'template_name':'list.html'}),
)
W wielu frameworkach MVC teraz musielibyśmy napisać kontrolery (widoki w Django) wykonujących określone czynności. Lecz Django posiada coś takiego jak Generyczne Widoki - przedefiniowane akcje takie jak: pokaż określony wpis, listuj wpisy ze stronicowaniem i inne. W powyższym kodzie urls.py użyliśmy generyczny widok django.views.generic.list_detail.object_list - listę wpisów ze stronicowaniem. Teraz musimy tylko stworzyć szablony.
Generyczne widoki to proste widoki i nie służą do tworzenia złożonych stron - od tego są własne widoki.

Szablony

  • W katalogu projektu utwórz katalog templates (na szablony) i site_media (na pliki statyczne)
  • Dodaj 'templates' (nazwę katalogu na szablony) w settings.py do TEMPLATE_DIRS
    TEMPLATE_DIRS = (
    	'templates',
    )
  • Edytuj urls.py i dodaj regułę:
    (r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.dirname(__file__), 'site_media')}),
  • Na początku urls.py dodaj import os.path.
  • Teraz wystarczy że stworzymy szablony. Żeby nasza przykładowa aplikacja wyglądała jak trzeba skorzystam z darmowego szablonu (zobacz | pobierz)
  • W przypadku powyższego szablonu otrzymamy po rozpakowaniu katalog images oraz pliki: default.css i index.html
  • Katalog i plik css kopiujemy do /site_media a index.html do /templates
  • Edytuj plik index.html i zastąp przykładową treść (tekst "newsów") tagiem: {% block content %}{% endblock %}, znajdź:
    <link rel="stylesheet" type="text/css" href="default.css" />
    
  • Zamień na:
    <link rel="stylesheet" type="text/css" href="/site_media/default.css" />
    
  • Utwórz plik /templates/list.html o kodzie:
    {% extends "index.html" %}
    {% block content %}
    	{% if object_list %}
    		{% for new in object_list %}
    			<h3>{{ new.title }}</h3>
    			<p>{{ new.text }}... {{ new.date|date:"d.m.Y" }}</p>
    		{% endfor %}
    		
    		{% if has_previous %}
    			<div style="text-align:center;"><a href="/?page={{ previous }}"><b>Nowsze Wiadomości</b></a></div>
    		{% endif %}
    		{% if has_next %}
    			<div style="text-align:center;"><a href="/?page={{ next }}"><b>Starsze Wiadomości</b></a></div>
    		{% endif %}
    	{% else %}
    		Brak wiadomości
    	{% endif %}
    {% endblock %}
    
  • Otwórz główną stronę swojej aplikacji w przeglądarce: http://localhost:8080/. Powinieneś zobaczyć coś takiego:
    django5
Trochę wyjaśnień, otóż zaczęliśmy od podaniu w settings.py nazwy katalogu na szablony, następnie w urls.py podaliśmy regułę obsługującą pliki statyczne pod serwerem deweloperskim (w warunkach produkcyjnych to serwer HTTP tym się zajmuje). Pliki statyczne to grafiki, pliki JS czy css jak i inne, do których chcemy mieć dostęp z poziomu aplikacji django. Kolejną czynnością było przystosowanie szablonu HTML. Przypomnijmy regułę serwującą statyczne pliki:
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.dirname(__file__), 'site_media')}),
r'^site_media/(.*)$' - oznacza iż wszystkie pliki statyczne dostępne są przez /site_media/plik_statyczny, tak więc musieliśmy zmienić odnośnik do pliku CSS. Kolejnym etapem było zastąpienie przykładowej treści przez tag bloku. Następnie stworzyliśmy drugi szablon dziedziczący index.html:
{% extends "index.html" %}
Szablony Django obsługują dziedziczenie - list.html dziedziczy index.html czyli wyświetli zawartość tego szablonu. Oprócz dziedziczenia skorzystaliśmy z drugiego ważnego elementu - bloków. W list.html podaliśmy zawartość dla bloku content:
{% block content %}
tutaj zawartość
{% endblock %}
W efekcie wypełniliśmy index.html określoną przez nas zawartością - listą newsów. Szablony jak i generyczne widoki opisane są w kolejnych artykułach. Na razie zakończymy rozwijanie bloga, lecz powrócimy do tego, gdy poznasz podstawowe komponenty Django: szablony, modele, ORM i widoki.
RkBlog

Django, 14 July 2008

Comment article
Comment article RkBlog main page Search RSS Contact