Wprowadzenie do Django - Tworzymy prostego bloga
Ten artykuł prezentuje sposób tworzenia aplikacji z wykorzystaniem Django. Jeżeli chcesz poznać ten framework to uważnie zapoznaj się z tym artykułem. Opanowując zaprezentowane tutaj podstawy będziesz mógł szybko i przyjemnie poznać kolejne elementy Django jak i zacząć tworzyć prawdziwe aplikacje www.
Zanim rzucisz się w wir tworzenia stron w Django zapoznaj się z jego kluczowymi komponentami. Wielu młodych programistów zbyt szybko zaczyna pisać aplikacje w Django i natrafia na problemy "jak coś zrobić", co kończy się tworzeniem "haków" i brzydkiego kodu. Django naprawdę wiele potrafi, trzeba tylko na spokojnie podejść do jego nauki :)
Instalacja Django
Zakładam że masz już Pythona zainstalowanego na komputerze i znasz jego podstawy. Django można zainstalować na dwa sposoby. Pierwszy poprzez PIP wykonując w konsoli polecenie:
Django można także zainstalować ręcznie pobierając pakiet ze strony djangoproject. Rozpakowujemy go a następnie w konsoli przechodzimy do katalogu z rozpakowanym Django i wykonujemy polecenie:
W przypadku Linuksa by zainstalować Django w systemie trzeba te polecenia wykonać z konta roota lub stosując "sudo" w dystrybucjach takich jak Ubuntu (dystrybucjach używających sudo). Dość często django jest w postaci pakietu w repozytorium - ale może być w nieco starszej wersji.
Co będzie nam jeszcze potrzebne?
Dla pełnej przyjemności przyda się nam edytor kodu, IDE obsługujące kod Pythona jak i szablony HTML, CSS, JS - wszystko co potrzebne jest do pisania kodu stron internetowych. Z aplikacji można wymienić Komodo Edit, Sublime Text 2, PyCharm, czy PyDev.
Django wykorzystuje bazy danych. Na potrzeby tego artykułu wykorzystam najprostszą - SQLite, dla której nie trzeba nic więcej instalować. W przypadku baz MySQL musimy zainstalować pakiet "mysql-python", a w przypadku baz PostgreSQL - "psycopg2" (instalujemy poprzez PIP). Dodatkowo do części frameworka powiązanych z grafikami/zdjęciami potrzebować będziemy pakietu "pil".
Tworzymy pierwszą stronę opartą o Django
Tworzenie projektu i aplikacji Django
Każdy serwis, strona internetowa stworzona za pomocą Django to projekt - katalog zawierający cały kod strony. W skład tego kodu wchodzą aplikacje - np. newsy, forum, artykuły to przykłady trzech możliwych aplikacji Django.
Zaczynamy od stworzenia projektu. W konsoli wykonujemy polecenie:
Polecenie to stworzy katalog projektu o podanej nazwie oraz stworzy w nim podstawowe pliki. Po wejściu do tego katalogu możemy tworzyć aplikacje za pomocą polecenia startapp. Ja stworzę teraz projekt "blog" i aplikację "news":
django-admin.py startproject blog cd blog python manage.py startapp news
Struktura projektu i aplikacji
W tej chwili w katalogu projektu "blog" mamy następującą strukturę plików i katalogów:blog
- __init__.py
- settings.py
- urls.py
- wsgi.py
news
- __init__.py
- models.py
- tests.py
- views.py
manage.py
Mamy więc podkatalog blog - nazwany tak samo jak projekt. Katalog ten przechowuje konfigurację projektu. settings.py przechowuje wszystkie ustawienia i to jego będziemy często odwiedzać. urls.py to drugi ważny plik - tutaj przypisujemy widok do podanego adresu URL. Dla programistów np PHP może to być spora nowość. Nie wywołujemy plików poprzez adresy URL, tylko przypisujemy widok/stronę jaka ma być wyświetlona dla podanego adresu URL (np. /news/ czy /forum/topic/1/ a nie news.php, czy forum.php?topic=1). Przy okazji od razu dostajemy "ładne" adresy URL.
Katalog news to katalog aplikacji. Każda aplikacja zaczyna z trzema istotnymi plikami:
- models.py: plik modeli aplikacji (każdy model opisuje tabelę w bazie danych, np. model newsów)
- views.py: plik zawierający kod widoków - funkcji lub klas, które spinają wszystko i zwracają pod podpięty adres URL kod HTML podstrony
- tests.py: ten plik może zawierać testy aplikacji. Nie jest wymagany choć w przyszłości przy tworzeniu bardziej złożonych aplikacji będą wskazane (na razie pomijamy ten plik).
Plik manage.py to w uproszczeniu lokalny odpowiednik django-admin.py. Można za jego pomocą tworzyć kolejne aplikacje, jak i wykonywać inne polecenia, o których dowiemy się za chwilę.
Aplikacje mogą zawierać dodatkowe pliki i katalogi (np. z szablonami) - o tym za chwilę, więc bez nerwów :)
Konfiguracja projektu w settings.py
Kolejny etap to konfiguracja bazy danych i innych ustawień w pliku settings.py. W tym artykule skorzystam z bazy SQLite konfigurując ją tak:DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'blog.sqlite',
# The following settings are not used with sqlite3:
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
Jak widzimy dla SQLite wystarczy podać typ bazy danych i nazwę pliku. Dla pozostałych (np. MySQL, PostgreSQL) trzeba podać nazwę użytkownika, jego hasło, jak i stworzyć bazę danych o podanej w konfiguracji nazwie.
W pliku settings.py mamy wiele opcji, każda opisana w komentarzu. Nie trzeba wszystkiego od razu sprawdzać i zmieniać. Ograniczę się do najbardziej podstawowych.
Zmieniamy domyślny język na polski: LANGUAGE_CODE = 'pl' oraz ustawiamy strefę czasową na TIME_ZONE = 'Europe/Warsaw'.
Ostatni element to INSTALLED_APPS - lista zainstalowanych aplikacji. Stworzyliśmy aplikację "news" i żeby projekt ją "widział" musimy dodać ją do listy:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'news',
)
Mając gotową konfigurację możemy utworzyć podstawowe tabele w bazie danych (te używane przez Django). Robimy to poleceniem:
Polecenie to służy do tworzenia tabel z "nowych" modeli. Gdy tworzymy nową aplikację z nowymi modelami ponownie odpalamy to polecenie by stworzyć brakujące tabele w bazie danych.
W czasie wykonywania tego polecenia za pierwszym razem Django spyta nas, czy chcemy stworzyć konto superużytkownika, który będzie miał dostęp do panelu admina:
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):
Wpisujemy "yes" i następnie podajemy logi, adres email oraz hasło użytkownika.
Serwer deweloperski
Django posiada wbudowany prosty serwer, który służy do odpalania projektu. Nie potrzebujemy żadnego innego serwera (jak np. Apache). By uruchomić serwer deweloperski wystarczy w katalogu projektu wydać polecenie:
Strona będzie dostępna pod adresem http://localhost:8000/
W warunkach produkcyjnych - gdy serwis jest skończony i dostępny w sieci nie używa się tego deweloperskiego serwera, tylko właśnie serwery takie jak Apache, Nginx odpowiednio skonfigurowane do obsługi projektu Django. Serwer deweloperski nie wymaga konfiguracji i ułatwia pracę programistom.
Panel Admina
Django posiada rozbudowany i generowany "automatycznie" Panel Admina dla naszych aplikacji. By go uruchomić upewnij się czy masz 'django.contrib.admin', dodane do INSTALLED_APPS (jeżeli nie to dodaj i wykonaj polecenie "syncdb"). Następnie edytuj plik urls.py do postaci (odkomentuj linie dotyczące panelu admina):from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
)

Modele
Każda tabela tworzona przez Django opisana jest modelem - klasą zawierającą definicje poszczególnych kolumn. Modele znajdują się w plikach models.py poszczególnych aplikacji. W naszym przypadku - news/models.py. Oto gotowe modele dla kategorii wiadomości i samych wiadomości:# -*- coding: utf-8 -*-
from django.db import models
class Category(models.Model):
name = models.CharField('Nazwa Kategorii', max_length=100)
slug = models.SlugField('Odnośnik', unique=True, max_length=100)
icon = models.ImageField('Ikonka Kategorii', upload_to='icons',
blank=True)
class Meta:
verbose_name = "Kategoria"
verbose_name_plural = "Kategorie"
def __unicode__(self):
return self.name
class News(models.Model):
title = models.CharField('Tytuł', max_length=255)
slug = models.SlugField('Odnośnik', max_length=255, unique=True)
text = models.TextField(verbose_name='Treść')
categories = models.ManyToManyField(Category, verbose_name='Kategorie')
posted_date = models.DateTimeField('Data dodania', auto_now_add=True)
class Meta:
verbose_name = "Wiadomość"
verbose_name_plural = "Wiadomości"
def __unicode__(self):
return self.title
Mamy model "Category" czyli kategorie wiadomości. Każda kategoria posiada nazwę ("name"), odnośnik ("slug", nazwa pozbawiona znaków niedopuszczanych w URLach - np polskich znaków), oraz ikonę - "icon".
Model wiadomości jest podobny - tytuł, odnośnik, treść ("text"), lista kategorii ("categories") oraz data dodania.
Jak widać każe z tych pól ma określony typ - models.CharField - pole tekstowe (VARCHAR), models.SlugField - pole tekstowe z walidacją znaków niedopuszczanych w odnośnikach, czy też np. models.TextField - pole tekstowe (TEXT). Pole ManyToManyField to pole relacji pozwalające przypisywać wiele kategorii do danej wiadomości. Django samo zajmie się stworzeniem tabel i obsługą relacji. Opis wszystkich pól i argumentów jakie przyjmują dostępny jest w oddzielnym artykule.
Praktycznie każde pole ma jako pierwszy argument podaną czytelną dla człowieka nazwę, np "Tytuł". To wartość argumentu "verbose_name", który używany jest w panelu admina. Zamiast wyświetlać surową nazwę możemy podać coś bardziej zrozumiałego. Tak samo klasy meta określają nazwy modelu używane w panelu - liczba pojedyncza i mnoga. Metoda __unicode__ zwraca tekstową wartość jaka będzie używana jako domyślny tekst dla rekordu modelu. W przypadku kategorii będzie to nazwa, a w przypadku wiadomości - tytuł.
Pole ImageField to specjalne pole tekstowe pozwalające przesłać na serwer plik graficzny. upload_to wskazuje katalog na pliki, a blank ustawione na False powoduje iż pole to jest opcjonalne.
Gdy mamy gotowy model możemy stworzyć tabele. Wystarczy ponownie wykonać:Panel Admina dla modeli
Dla Django konfiguracja Panelu Admina dla modeli odbywa się poprzez plik admin.py umieszczony w katalogu aplikacji (news/admin.py). Oto najprostszy przypadek udostępniania modeli w PA:# -*- coding: utf-8 -*-
from django.contrib import admin
from news.models import *
admin.site.register(Category)
admin.site.register(News)


# -*- coding: utf-8 -*-
from django.contrib import admin
from news.models import *
class CategoryAdmin(admin.ModelAdmin):
list_display = ('name', 'icon')
prepopulated_fields = {'slug': ('name',)}
class NewsAdmin(admin.ModelAdmin):
list_display = ('title', 'posted_date')
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Category, CategoryAdmin)
admin.site.register(News, NewsAdmin)

Widoki
Django stosuje wzorzec projektowy Model-Szablon-Widok, gdzie logika bazodanowa jest w modelu, szablon określa wygląd (HTML), a widok spina to razem zwracając gotowy wynik (gotową stronę). Widoki definiowane są w pliku views.py aplikacji (news/views.py). Oto prosty widok:# -*- coding: utf-8 -*-
from django.template import RequestContext
from django.shortcuts import render_to_response
from news.models import *
def index(request):
return render_to_response('index.html',
{'zmienna': 'Jestem widokiem'},
context_instance=RequestContext(request))
<h1>Moja Strona </h1>
{{ zmienna }}
Odnośniki
W Django odnośniki, pod którymi są dostępne określone widoki są mapowane za pomocą reguł z wyrażeniami regularnymi w plikach urls.py. W naszym pliku urls.py mamy już podaną regułę dla panelu admina, teraz musimy podać regułę dla naszego widoku index:from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^/?$', 'news.views.index'),
)

Operowanie na danych, ORM
Mając modele możemy operować na nich (pobierać, dodawać, czy edytować dane) poprzez ORM Django. Standardowo dostęp do modelu uzyskujemy poprzez:def index(request):
news = News.objects.all().order_by('-posted_date')
return render_to_response('index.html',
{'news': news},
context_instance=RequestContext(request))
<h1>Moja Strona </h1>
{% for entry in news %}
<h3>{{ entry.title }}</h3>
{{ entry.text|safe }}<br />
{{ entry.posted_date|date:"Y.m.d H:i" }}
{% endfor %}

Comment article