You are on page 1of 7

Technikę

Python kontra PHP


czyli węże i słonie

Trend web 2.0 przyniósł ze sobą nie tylko nowe podejście do tworzenia
stron internetowych, ale również nowe technologie i narzędzia. Wielu z nas
słyszało lub miało kontakt z Ruby on Rails, a użytkownicy portalu grono.net
korzystali z aplikacji napisanej w Django.
wiązań, które zostały wykorzystane w wie-
Dowiesz się... Powinieneś wiedzieć... lu projektach.
• Zapoznasz się z nowymi narzędziami do two- • Podstawowa znajomość PHP i wzorca MVC. Niestety na większości kont hostingowych
rzenia stron www. wciąż dominuje PHP4. Wydanie PHP6 jesz-
cze bardziej spotęguje to zjawisko, a progra-
miści oprócz wykonania swojej pracy będą
• Działają na wielu platformach i architek- musieli co chwilę uwzględniać wersję PHP,
turach. pod którą ma działać ich aplikacja.
Poziom trudności
Mimo podobieństw są to dwa różne języki. Python dla programisty PHP
Zbiór różnic przedstawia Tabela 1. Programista PHP dość szybko może połapać
Nie ulega wątpliwości, że PHP jest popular- się w konkurencyjnym języku, choć będzie

W
królestwo PHP zaczynają wkra- ny i ma bardzo dużą społeczność, również w musiał przyzwyczaić się do pewnych różnic.
czać inne języki oferując kon- Polsce. Znalezienie pomocy, czy to w postaci Pierwszą jest brak średnika na końcu linii,
kurencyjne rozwiązania, które opublikowanych materiałów, czy też w posta- drugą grupowanie kodu za pomocą wcięć. Pę-
to omówimy w tym artykule. Cytując wiki- ci forum dyskusyjnego to nie problem. Rów- tla for w PHP wygląda znajomo:
pedię Python jest interpretowanym, interak- nież praktycznie każdy darmowy, tani ho-
tywnym językiem programowania stworzo- sting będzie zawierał w ofercie obsługę skryp- <?PHP
nym przez Guido van Rossuma w 1990 ro- tów PHP. for($i=1;$i <=5;$i++)
ku. Rozwijany jest jako projekt Open Source, Python ma mniejszą społeczność, w Pol- {
zarządzany przez niedochodową Python So- sce jest raczej mało popularny, lecz w skali print $i.'<br />';
ftware Foundation. PHP to wykonywany po światowej społeczność jest dość duża i sku- }
stronie serwera skryptowy język programo- piona wokół mniejszej ilości serwisów i orga- ?>
wania służący do generowania stron inter- nizacji. W kwestii hostingu umożliwiające-
netowych. Python tak samo jak Ruby sam go obsługę aplikacji Zope, Django czy Pylons W Pythonie wyglądać może tak:
z siebie nie jest przystosowany do tworzenia nie będziemy mieć licznego grona kandyda-
stron www, jako że jest to język uniwersal- tów, lecz jakość usług będzie wysoka (np. for i in range(1,6):
ny od początku swojego istnienia. PHP nato- WebFaction). Skrypty PHP wystarczy umie- print i
miast od początku tworzony był jako język ścić na serwerze, korzystając np. z klien-
do tworzenia stron www. W niniejszym ar- ta FTP. W przypadku aplikacji wspomnia- Nieco większą różnicą jest brak tablic zna-
tykule skupimy się nie tyle na porównaniu nych frameworków praktycznie nieodzow- nych z PHP, a obecność list, tupli i dzienni-
języków, ale frameworków napisanych w Py- ny będzie dostęp do shella oraz odpowied- ków. Pierwsze dwa typy uznać można za tabli-
thonie i PHP. nia konfiguracja serwera www. Framewor- ce numeryczne, a dzienniki za tablice asocja-
ki Pythonowe nie nadają się więc jako „Mo- cyjne. Oto przykład:
Różnice i podobieństwa ja pierwsza strona”.
Oba języki mają wiele wspólnego, ponieważ są: Kolejnym punktem, który warto poruszyć dziennik = {'klucz': 'wartosc'}
to wsteczna zgodność Pythona. Aplikacja pi- print dziennik['klucz']
• Interpretowalnymi językami wysokiego sana pod Pythonem 2.5 będzie w stanie dzia- lista = ['element1', 'element2']
poziomu z dynamicznym systemem ty- łać pod Pythonem 2.3. Potencjalne zmiany w print lista[1]
pów; kodzie ograniczą się do zmian nazw modu- print lista[0]
• Rozwijane jako projekty OpenSource; łów czy sposobu ich użytkowania (chyba że tupla = ['element tupli1', 'element
• Posiadają duże społeczności; użyjemy „starszej” nazwy modułu). W przy- tupli2']
• Łatwe w nauce (w porównaniu do np. Javy); padku PHP jest jeden problem. PHP5 udo- for i in tupla:
• Łatwe do rozszerzenia poprzez C/C++; stępniło programistom wiele dobrych roz- print i

28 04/2007
Python kontra PHP

Nowością będzie przestrzeń nazw i importo- nia aplikacji – dla Apache mamy mod_python go systemu szablonów. Krótkie porównanie
wanie modułów. W przypadku PHP w skryp- i mod_fcgid, dla Lighttpd, Cherokee czy przedstawia Tabela 2.
cie mamy dostęp do wszystkich funkcji i klas Nginx możemy wykorzystać protokół FastC- Oba frameworki są bardzo dobrymi rozwią-
danej instalacji PHP. W przypadku Pythona GI lub SCGI. zaniami. Django jest frameworkiem najlepiej
by uzyskać dostęp np. do klas obsługujących Za chwilę poznamy bliżej framework Django. pasującym do aplikacji typu CMS. Pylons ma
pliki ZIP musimy zaimportować odpowied- W jego przypadku dodanie keszowania dla całe- podejście „zrób to sam” i króluje w przypad-
ni moduł: go projektu, to dodanie jednego wiersza w usta- kach, gdy wymagamy elastyczności i stawiamy
wieniach, a do keszowania możemy użyć m.in. nietypowe wymagania.
import zipfile memcache – wydajnego systemu bazującego na Portale takie jak Grono.net i lawrence.com
z = zipfile.ZipFile("plik.zip", "r") pamięci RAM. wykonane są w Django – i są dużymi serwisa-
for plik in z.namelist(): Stosując Pythona do tworzenia dynamicz- mi internetowymi. Poradnikzdrowie.pl to ser-
print 'Plik: ', plik, nych stron www, na pewno nie stracimy na wy- wis napisany w Pylons zintegrowany z RedDo-
bajty = z.read(plik) dajności gotowych aplikacji, a nawet dość często tem (istniejącą wcześniej strukturą serwisów
print 'ma', len(bajty), 'bajtow' nawet zyskamy. właściciela). Serwisy te dobrze obrazują różni-
ce między Django a Pylons.
Wydajność i skalowalność Frameworki Pythona
Oba języki są interpretowane (do wykonania W Pythonie znajdziemy kilka (a nie kil- WSGI
skryptu używa się interpretera), lecz PHP nie kadziesiąt i więcej) frameworków do two- WSGI czyli Web Server Gateway Interface to
jest kompilowany do bajtkodu i zapisywany rzenia stron www, które można wykorzy- standard interfejsu aplikacji napisanej w Py-
do wielokrotnego użytku. Każde żądanie wy- stać. Prym wiedzie Django i Pylons, a trze- thonie do porozumiewania się z serwerami.
słane do serwera spowoduje zinterpretowanie ci – TurboGears znajduje się obecnie w fa- Stworzono standard interfejsu, który obec-
i wykonanie kodu w locie. W przypadku Py- zie przejściowej między starą i stabilną se- nie stosowany jest przez wiele pythonowych
thona kompilacja do bajtkodu jest automa- rią 1.X a przygotowywaną serią 2.X zgodną aplikacji, głównie frameworków i aplikacji
tyczna, natomiast użytkownicy PHP muszą z WSGI. Dobrze znane od dawna Zope i Plo- sieciowych.
skorzystać z kompilatorów nie wchodzących ne też ewoluują, lecz to Pylons i Django pod Przestrzeganie standardu ułatwiło współ-
w skład domyślnej dystrybucji PHP, takich sztandarem nowoczesności i web 2.0 ataku- pracę wielu aplikacji ze sobą i z serwera-
jak Xcache, eaccelerator, APC czy produktów ją układ LAMP. mi – pojawiło się pojęcie middleware, czyli
firmy Zend. W bezpośrednim starciu bez za- Django to framework dla „profesjonalistów z skryptu o określonym interfejsie, modyfiku-
biegów optymalizacyjnych Python wygra, terminami”, jak głosi jego motto. Jest to dobrze jącym żądanie bądź odpowiedź wysyłaną do
lecz odpowiednio skonfigurowane PHP nie zintegrowany zestaw własnych komponentów lub z serwera.
będzie miało się czego wstydzić. takich jak ORM wysokiego poziomu, system Dany skrypt middleware może być bez mo-
Python i niektóre jego frameworki mo- szablonów czy mapper adresów URL. Pylons dyfikacji stosowany w każdym frameworku,
gą działać wielowątkowo, co jest wydajniej- to framework bazujący na integracji „najlep- zgodnym z wytycznymi WSGI, co stanowi
sze od zwykłego trybu pracy PHP, jako że ta- szych ze swojego rodzaju” rozwiązań. ogromne pole do rozbudowy narzędzi tego
ki tryb pracy zużywa mniej zasobów. Rów- Wykorzystuje on istniejące podzespoły jak typu o nowe możliwości. Przykładem jest tu
nież w przypadku Django czy Pylons może- również umożliwia łatwą ich wymianę, tak framework Pylons stawiający na WSGI. Sam
my skorzystać z różnych sposobów hostowa- więc nie jesteśmy ograniczani do np. jedne- nie posiada ani systemu użytkowników, ani
Tabela 1. Różnice pomiędzy językami PHP i Python
PHP Python
Składnia bazująca na C i Perlu Wcięcia stosowane do grupowania kodu
Instrukcje swith i do... while Przestrzenie nazw
Brak przestrzeni nazw Wszystko jest referencją
Nawiasy klamrowe stosowane do grupowania kodu Wielowątkowość
Większa społeczność i popularność Dużo typów wysokiego poziomu
Język głównie do tworzenia dynamicznych stron Język ogólnego użytku
Stabilny, lecz gwałtowniej rozwijany (PHP4 – PHP5) Wstecznie zgodny, stabilny i dojrzały. Standaryzacja rozwiązań
Kompilatory dostępne jako rozszerzenia (APC, Xcache, eaccelerator, zend) Automatyczne kompilowanie do bajtkodu

Tabela 2. Porównanie frameworków Pythona


Django Pylons
Dobrze zintegrowane własne komponenty Integruje najlepsze istniejące komponenty i umożliwia ich łatwą wymianę
Łatwy w nauce, świetnie udokumentowany Niespójna i mniej liczna dokumentacja (każdy komponent ma dokumenta-
cję na swojej stronie). Wymaga więcej czasu na naukę i konfigurację kom-
ponentów
ORM wysokiego poziomu obsługujący MySQL, Zalecane stosowanie ORMa SQLAlchemy – większe możliwości i łatwiejsza
SQLite i PostgreSQL (Oracle od wersji 1.0) praca na istniejących tabelach, lecz trudniejszy w nauce.
Większa społeczność, zastosowany w wielu projektach Aplikacja może działać wielowątkowo
Generyczne widoki, Automatyczny panel admina, system użytkowników i Wiele pomocników JavaSript, Ajax (w tym Scriptaculous)
uprawnień

www.phpsolmag.org 29
Technikę

obsługi openID, ale middleware, takie jak np. Django kontra Instalacja
AuthKit, bezproblemowo dodają te funkcjo- CodeIgniter i spółka Ostatnią wydaną wersją Django jest wersja
nalności do frameworka. Chęć przestrzega- Zajmiemy się teraz porównaniem obu frame- 0.96. Pobieramy archiwum z frameworkiem ze
nia specyfikacji jest w społeczności tak du- worków, jak i drogi tworzenia aplikacji z ich strony projektu i rozpakowujemy. Otwieramy
ża, że trzeci duży framework – TurboGears użyciem (CodeIgniter opisany został w nume- konsolę i przechodzimy do katalogu z kodem
zawiesił rozwój dotychczasowego niezgodne- rze 2/2007 phpSolutions). Django wykorzystuje Django. Wydajemy polecenie:
go z WSGI drzewa 1.X tworząc zarazem roz- wzorzec MVC , lecz w porównaniu z CI wpro-
wojową obecnie gałąź 2.X, zgodną z WSGI. wadza kilka zmian. Pierwszą z nich jest nazwa python setup.py install
Dla programistów rozwijających framewor- – MTV czyli Model-Template-View. W Django
ka oznacza to przepisanie wielu modułów model określa strukturę tabeli (logikę bazoda- Django wymaga kilku dodatkowych bibliotek
TurboGears. nową ogólnie), widok zawiera logikę aplikacji, Pythona:
W PHP standaryzacja rozwiązań kuleje. Na- a szablon wygląd. Kolejna różnica dotyczy sa-
wet na poziomie nazw funkcji trafimy na róż- mego modelu. W przypadku CodeIgnitera mo- • Do obsługi SQLite Django używa pysqlite;
ne style nazewnictwa. W kategorii komponen- del zawierał definicje różnych operacji na ba- • Postgres: psycopg;
tów sprawę nieco wyjaśnia PEAR, lecz czy Co- zie danych, takich jak pobieranie ostatnich • MySQL: mysql-python.
deIgniter, Symfony lub Zend Framework bez- newsów, kasowanie i aktualizowanie wpisów.
boleśnie integrują API pakietów PEAR? Nie- W Django model definiuje strukturę tabeli, a Tworzenie aplikacji w Django
stety nie. operacje wykonujemy w widokach za pomo- Tworzenie projektu. Projekt składa się z aplika-
Zend Framework i ezComponents jako zbiór cą ORMa. cji, np. CMS z różnych modułów. By stworzyć
luźniejszych komponentów, które łatwiej wy- projekt wystarczy wydać polecenie:
korzystywać w innych frameworkach, dają na- Przykładowy projekt Django
dzieję, lecz na tak daleko posuniętą standary- Zaprezentuję teraz prosty projekt Django – blog django-admin.py startproject NAZWA_PROJEKTU
zację jak w przypadku Pythona nie mamy na z systemem newsów obrazujący sposób tworze- django-admin.py startproject blog
razie co liczyć. nia projektów Django.
Stworzone zostaną podstawowe pliki projek-
tu, możemy nawet uruchomić serwer Django
Listing 1. Podłączenie bazy danych do naszego CMSa
dla tego projektu.
DATABASE_ENGINE =
'sqlite3' # 'postgresql', 'mysql', 'sqlite3' lub 'ado_mssql'. Uruchamianie serwera Django
DATABASE_NAME = Z konsoli po przejściu do katalogu projektu wy-
'bazka.db' # nazwa bazy danych lub ścieżka dla bazy sqlite3 konaj polecenie:
DATABASE_USER =
'' # użytkownik bazy, puste dla sqlite3 python manage.py runserver 8080
DATABASE_PASSWORD =
'' # hasło użytkownika, puste dla sqlite3 Komenda ta uruchomi deweloperski serwer
DATABASE_HOST = Django. Będzie on dostępny pod adresem http:
'' # host do bazy danych, puste localhost //localhost:8080/.
DATABASE_PORT =
'' # Podaj port jeżeli niestandardowy, puste dla sqlite3. Konfiguracja projektu – bazy danych
następnie zmieniamy język i strefę czasową: Django jest silnie powiązane z bazami danych
TIME_ZONE = 'Europe/Warsaw' i do dalszych operacji będzie nam potrzeb-
LANGUAGE_CODE = 'pl' na dostępna baza danych (sqlite3, mysql lub
postgresql). Edytujemy settings.py i ustawia-
Listing 2. Model aplikacji wiadomości my SQLite jako naszą bazę danych: patrz Li-
from django.db import models sting 1.
class News(models.Model): Teraz zatrzymujemy serwer Django i syn-
news_title = models.CharField( chronizujemy bazę danych. Po dodaniu nowej
maxlength=255, verbose_name='Tytuł') aplikacji, bądź danych do bazy danych nowe-
news_text = models.TextField( go projektu, musimy te dane zsynchronizować.
verbose_name='Treść') Służy do tego polecenie:
news_date = models.DateTimeField(
auto_now_add = True, blank= python manage.py syncdb
True, verbose_name='Data dodania')
class Meta: W przypadku rozpoczynania pracy z bazą da-
verbose_name = "Wiadomość" nych Django zapyta nas też o dane głównego
verbose_name_plural = "Wiadomości" admina projektu.
class Admin:
list_display = ('news_title', 'news_date') Tworzenie aplikacji
list_filter = ['news_date'] By stworzyć aplikację wystarczy wykonać pole-
search_fields = ['news_title', 'news_text'] cenie z katalogu projektu:
date_hierarchy = 'news_date'
def __str__(self): python manage.py startapp
return self.news_title NAZWA_APLIKACJI
python manage.py startapp news

30 04/2007
Python kontra PHP

Co stworzy katalog aplikacji wraz z plikami: Szablony Teraz wystarczy, że stworzymy szablo-
ny. Skorzystamy z darmowego szablonu.
news/ • W katalogu projektu utwórz katalog Załóżmy, że zawiera on XHTML zawie-
__init__.py templates (na szablony) i site _ media ra katalog images oraz pliki: default.css i
models.py (na pliki statyczne); index.html .
views.py • Dodaj 'templates' (nazwę katalogu na sza-
blony) w settings.py do TEMPLATE _ • Katalog i plik css kopiujemy do /site _
Zbiór models.py zawiera modele naszej aplika- DIRS. media a index.html do /templates ;
cji. Kod modelu dla naszej przykładowej apli- TEMPLATE_DIRS = ( • Edytujemy plik index.html i zastępujemy
kacji przedstawia Listing 2. 'templates', przykładową treść tagiem:
Każdy model, klasa dziedziczy z ) {% block content %}{% endblock %};
django.db.models.models, przez co może- • Znajdujemy <link rel="stylesheet"
my zdefiniować strukturę poszczególnych Edytuj plik urls.py i dodaj regułę: type="text/css" href="default.css" /> ;
tabel. Pole CharField i TextField służą do prze- • Zamieniamy na <link rel="stylesheet"
chowywania tekstu, DateTimeField daty. Te- (r'^site_media/(.*)$', 'django.views.static type="text/css" href="/site _ media/
raz edytujemy settings.py projektu. Do IN- .serve', default.css" /> ;
STALLED_APPS dodajemy naszą aplikację {'document_root': '/ŚCIEŻKA/DO/site_ • Tworzymy plik /templates/news _
(NAZWA_PROJEKTU.NAZWA_APLIKA- media'}), list.html z kodem: Listing 4.
CJI), czyli blog.news. Zapisujemy i synchroni-
zujemy bazę danych.
Listing 3. Dopasowanie adresów URL w urls.py

Panel Admina from django.conf.urls.defaults import *


By włączyć panel administracyjny wykonu- from blog.news.models import *
jemy: urlpatterns = patterns('',
(r'^admin/', include(
• Do INSTALLED_APPS w settings.py doda- 'django.contrib.admin.urls')),
jemy django.contrib.admin; (r'^/?$', 'django.views.generic.
• Synchronizujemy bazę danych; list_detail.object_list', {
• Edytujemy urls.py i usuwamy komentarz 'queryset':News.objects.all().
(#) z wiersza: order_by('-id'), 'paginate_by':10,
(r'^admin/', include('django.contrib. 'allow_empty':True, 'template_name':
admin.urls')), 'news_list.html'}),
(r'^/(?P<page>[0-9]+)$',
Panel Admina dostępny jest pod adresem 'django.views.generic.list_detail.object_list',
http://localhost:8080/admin/ i umożliwia {'queryset':News.objects.all().order_by('-id'),
zarządzanie aplikacją – dodawanie, usu- 'paginate_by':10, 'allow_empty':True,
wanie i edytowanie wpisów wraz z opcja- 'template_name':'news_list.html'}),
mi pomocniczymi jak listowanie i wyszu- )
kiwanie.
Listing 4. Przykładowy plik news_list.html
Interfejs użytkownika {% extends "index.html" %}
Mamy gotowy panel administratora wiado- {% block content %}
mości, lecz nie mamy jeszcze interfejsu od {% if object_list %}
strony użytkownika. Zaczynamy od zapro- {% for new in object_list %}
jektowania adresów URL. urls.py zawierają <h3>{{ new.news_title }}</h3>
listę powiązanych adresów URL z akcjami <p>{{ new.news_text }}... {{
wywoływanymi w przypadku dopasowania new.news_date|truncatewords:"1" }}</p>
URLa. Format: {% endfor %}

(wyrażenie regularne, funkcja pythona {% if has_previous %}


do wykonania [, opcjonalnie katalog]) <div style="text-align:center;">
<a href="/?page={{ previous }}">
urls.py powinien wyglądać tak: Listing 3. <b>Nowsze Wiadomości</b></a></div>
W wielu frameworkach MVC, w tym miej- {% endif %}
scu, musielibyśmy napisać kontrolery (wido- {% if has_next %}
ki w Django) wykonujące określone czynno- <div style="text-align:center;">
ści. Lecz Django posiada coś takiego, jak Gene- <a href="/?page={{ next }}">
ryczne Widoki, czyli predefiniowane akcje ta- <b>Starsze Wiadomości</b></a></div>
kie jak: pokaż określony wpis, listuj wpisy ze {% endif %}
stronicowaniem i inne. W powyższym kodzie {% else %}
urls.py użyliśmy generycznego django.vie Brak wiadomości
ws.generic.list_detail.object_list – li- {% endif %}
sty wpisów ze stronicowaniem. Teraz musi- {% endblock %}
my tylko stworzyć szablony.

www.phpsolmag.org 31
Technikę

Otwieramy główną stronę swojej aplika- świetla zawartość tego szablonu. Oprócz dzie- mie modelu poprzez wysokopoziomowe
cji w przeglądarce, wpisując adres http:// dziczenia skorzystaliśmy z drugiego ważnego typy pól.
localhost:8080/. Efekt przedstawiono na Ry- elementu – bloków. W news_list.html podali-
sunku 2. śmy zawartość dla bloku content: Smaczki Django
Trochę wyjaśnień, otóż zaczęliśmy od poda- Prezentowana przed chwilą aplikacja, nie
nia w settings.py nazwy katalogu na szablony, {% block content %} pokazała wszystkich możliwości framewor-
następnie w urls.py podaliśmy regułę obsługu- tutaj zawartość ka. Poznanie ich wymaga bardziej dokładne-
jącą pliki statyczne pod serwerem deweloper- {% endblock %} go poznania tego narzędzia, lecz poniżej opi-
skim (w warunkach produkcyjnych to serwer szę kilka innych przydatnych komponentów
www tym się zajmuje). Pliki statyczne to gra- W efekcie wypełniliśmy index.html określoną Django.
fiki, pliki JS czy css, jak i inne, do których chce- przez nas zawartością – listą newsów. Oczy-
my mieć dostęp z poziomu aplikacji Django. Ko- wiście możemy stworzyć identyczną aplika- ORM Django
lejną czynnością było przystosowanie szablonu cję w PHP, lecz kluczowym czynnikiem jest ORM mapuje strukturę bazy danych – po-
HTML. Przypomnijmy sobie regułę serwującą tutaj szybkość tworzenia. Django jest bardzo szczególnych tabel na obiekty. W Django obsłu-
statyczne pliki: dobrym narzędziem, gdyż jego komponenty ga ORMa jest bardzo prosta, a sam komponent
umożliwiają bardzo wydajne tworzenie wyso- jest mocno rozbudowany. Propel dostępny dla
(r'^site_media/(.*)$', 'django.views.static kiej jakości aplikacji. W porównaniu do takie- PHP niestety nie może pochwalić się tak czy-
.serve', go samego programu wykonanego w CodeIgni- stym i przyjemnym interfejsem.
{'document_root': '/ŚCIEŻKA/DO/site_ terze różnice są następujące: Listing 5. przedstawia model dla systemu
media'}), blogów złożony z trzech tabel. Blog – nazwa i
• Nie tworzymy tabeli w bazie danych, robi opis blogów, Author – Nazwisko i email auto-
r'^site _ media/(.*)$' – oznacza, iż to framework (dbając m.in. o indeksy); rów. Entry – wpis dla danego bloga.
wszystkie pliki statyczne dostępne są przez • Mamy gotowy Panel Admina do zarządza- Zaprezentowany na listingu model prezen-
/site_media/plik_ statyczny, tak więc musie- nia aplikacjami; tuje obsługę powiązanych tabel – Entry ma
liśmy zmienić odnośnik do pliku CSS. Ko- • Generyczne Widoki znacznie ułatwiają pole authors zależne od Author i pole blog za-
lejnym etapem było zastąpienie przykłado- tworzenie interfejsu od strony użytkowni- leżne od Blogs. Proste zależności wiele-do-
wej treści przez tag bloku. Następnie stwo- ka; jednego określane są przez pola typu Foreign-
rzyliśmy drugi szablon dziedziczący in- • Model opisuje tabele bazy danych, a nie Key, zawierające jako parametr nazwę mode-
dex.html: operacje na nich – w przypadku CI bez lu. Tak więc dany wpis (Entry) przypisany jest
struktury tabel trudno byłoby je odtwo- do konkretnego autora i bloga. Django oferu-
{% extends "index.html" %} rzyć bazując na kodzie modeli (brak wy- je również obsługę zależności wiele-do-wielu
cieku informacji poza projekt); czyli np. gdyby taka zależność dotyczyła pola
Szablony Django obsługują dziedziczenie – • Walidacja na poziomie mapowania URLi blog, to dany wpis (Entry) mógłby być przy-
news_list.html dziedziczy index.html, czyli wy- poprzez wyrażenia regularne i na pozio- pisany do wielu blogów. Listing 6. przedsta-
wia operacje na rekordach wykonywane po-
przez ORM.

System uprawnień i użytkowników


Django oferuje również system użytkowni-
ków, grup oraz uprawnień. Przy synchroniza-
cji bazy danych mogłeś zauważyć, że dla każ-
dego modelu (klasy) tworzone są domyślnie
trzy „znaczniki” uprawnień: dodawanie, edy-
cja i usuwanie obiektu danego modelu. Można
też tworzyć własne. W Panelu administracji w
łatwy sposób możemy tworzyć grupy, zbiory
Rysunek 1. Panel Admin w akcji uprawnień jak również nadawać poszczegól-
nym użytkownikom uprawnienia i przypisy-
wać ich do istniejących grup. Wykorzystanie
tego systemu w praktyce jest bardzo łatwe, ja-
ko że w widoku bieżący użytkownik reprezen-
towany jest przez obiekt request.user. Najlepiej
obrazuje to Listing 7. zawierający kod proste-
go widoku.

Middleware
Middleware to pojęcie związane z WSGI,
obecnym również w Django. Middleware
może globalnie wpływać na żądania wysy-
łane do widoków, jak i na ich odpowiedzi.
Do czego można zastosować middleware?
Np. do śledzenia aktywności użytkowników
na stronie – każde żądanie dowolnej strony
Rysunek 2. Widok strony głównej wiadomości

32 04/2007
Python kontra PHP

naszej aplikacji może wykonać kod middle- Zedo.pl – Dlaczego Django? Nie jest to nic, czego nie można zrobić w PHP,
ware, aktualizujący listę użytkowników Na Zedo.pl to nowo powstały portal społeczno- ale tutaj liczy się czas programisty i wysiłek ja-
Stronie. Może też posłużyć do modyfikacji ściowy, w którym użytkownicy dzielą się ki należy włożyć, by uzyskać założony efekt.
nagłówków, czy zmiany działania serwisu komponentami do telefonów komórkowych, Django zawiera dobry system użytkowników i
w określonych warunkach (np. obsługa ope- takimi jak tapety i w przyszłości motywy czy uprawnień oraz rozbudowany, elastyczny sys-
nID w Pylons). dzwonki. Pierwotnie właściciel chciał, by ser- tem walidacji i obsługi formularzy, dzięki te-
wis był wykonany w znanej mu technologii mu dość łatwo rozwiązać możliwe problemy:
Maper adresów URL – PHP i MySQL, lecz gdy zapoznałem go z
Jak już mogliśmy zauważyć w Django (w Py- Django i jego możliwościami zgodził się na to • Skrypt Middleware w przypadku zalogo-
lons również) adresy URL są mapowane, co rozwiązanie. Dlaczego wybrałem Django? Ze wanego użytkownika, co 5 minut aktuali-
w PHP jest niespotykane. Za pomocą wyra- względu na szybkość i przyjemność tworze- zuje jego obecność na stronie, wykorzystu-
żeń regularnych określamy URL i przypi- nia kodu aplikacji. Główne problemy, jakie jąc cookie z zapisanym znacznikiem czasu,
sujemy mu widok, jaki ma zostać wykona- dostrzegłem po zapoznaniu się ze specyfika- do określania czy i kiedy zaktualizować
ny. URLe, które nie zostaną dopasowane do cją portalu to: wpis w bazie danych;
żadnego wyrażenia nie istnieją (zwrócony zo- • Do walidacji wysyłanych tapet, oprócz
stanie kod 404). Wymaga to od programisty • Rozbudowany system użytkowników walidacji rozszerzenia wykorzystany zo-
znajomości podstaw wyrażeń regularnych. wraz z „użytkownikami online”, rozbudo- stał PIL do walidacji rozmiaru i typu MI-
W efekcie dostajemy przyjazne wyszukiwar- wanymi profilami z komentarzami, przy- ME (wykrywa łączone pliki typu grafika-
kom odnośniki oraz w przypadku zastosowa- jaciółmi itp.; +PHP);
nia poprawnych formuł – walidację na pozio- • Walidacja formularzy, w szczególności do- • System użytkowników został rozszerzony
mie mapowania odnośników (nie trzeba tego dawanie tapet (walidacja i skalowanie pli- o zależne tabele zapewniające funkcjonal-
robić w widoku). Mapowane adresy URL to ków); ność profilu użytkownika.
nie przepisany Query String, który również • Powiązane między sobą tabele (Komór-
istnieje i może być stosowany w wyjątkowych ki z przypisaną rozdzielczością – tapeta o Nietypowe rozwiązania
okolicznościach (zaleca się stosowanie mapo- określonej rozdzielczości) i filtrowanie da- Python to język ogólnego przeznaczenia, istnie-
wanych odnośników). nych z powiązanych tabel. je więc wiele komponentów, które nie były two-

R E K L A M A
Technikę

rzone z myślą o stronach www, co nie oznacza,


W Sieci: że nie możemy ich wykorzystać. Chcąc zro-
bić bazę danych wyników analiz chromato-
• http://www.python.org – strona Pythona; graficznych – wystarczy skorzystać z bibliote-
• http://www.ipersec.com/index.php?q=en/bench_ea_vs_apc – porównanie wydajności róż-
ki pyCDF i zapisać wyniki w formacie CDF. Je-
nych enkoderów bajtkodu PHP;
• http://www.python.org/dev/peps/pep-0333/ – opis WSGI; żeli chcemy generować złożone wykresy z tych
• http://wiki.rubyonrails.com/rails/pages/Framework+Performance – porównanie wydajności analiz, lub z innych danych, problem nasz roz-
Symfony, Ruby on Rails i Django; wiąże matplotlib. Generowaniem raportów, pli-
• http://twistedmatrix.com/trac/ – strona frameworka Twisted; ków PDF czy prostych wykresów zajmie się re-
• http://www.djangoproject.com – strona Django;
portlab, a skanowaniem przesyłanych załącz-
• http://www.pylonshq.com – strona Pylons;
• http://www.python.rk.edu.pl/ – polska dokumentacja Django i Pylons ników, pod kątem obecności wirusów, pyCla-
• http://docs.pythonweb.org/ – wiki Pylons mAV. Odpowiednikiem GD z PHP będzie PIL
o równie bogatej, jeżeli nie większej funkcjo-
nalności.
Listing 5. Model systemu blogów
Programowanie sieciowe
class Blog(models.Model): Python w swojej bibliotece standardowej po-
name = models.CharField(maxlength=100) siada szereg modułów przydatnych przy pro-
tagline = models.TextField() gramowaniu sieciowym. Moduł socket, jak sa-
def __str__(self): ma nazwa wskazuje, daje nam możliwość ope-
return self.name rowania na gniazdach. Moduły wyższego po-
class Author(models.Model): ziomu jak urllib, telnetlib, imaplib czy ftplib
name = models.CharField(maxlength=50) zapewniają obsługę poszczególnych protoko-
email = models.URLField() łów. Nie jest to nic nadzwyczajnego. Wymaga-
def __str__(self): jących zapewne zainteresuje coś innego – fra-
return self.name mework sieciowy Twisted, wspierający TCP,
class Entry(models.Model): UDP, SSL/TLS, multicast czy protokoły takie
blog = models.ForeignKey(Blog) jak HTTP, NNTP, IMAP, SSH, IRC, FTP. Fra-
headline = models.CharField(maxlength=255) mework ten umożliwia pisanie asynchronicz-
body_text = models.TextField() nych klientów i serwerów różnego typu.
pub_date = models.DateTimeField()
authors = models.ManyToManyField(Author) Test Driven Development
def __str__(self): Testy jednostkowe i ciągła kontrola rozwija-
return self.headline nej aplikacji w przypadku dużych projektów
jest nieodzowna. Również w Pythonie znaj-
Listing 6. Przykładowe operacje ORMa django dziemy narzędzia do przeprowadzania ta-
# Dodanie wpisu kich testów. Dostępnych jest kilka rozwiązań
b = Blog(name= 'Blog Andrzeja', tagline= jak: unittest, pymock, nose, nosy czy py.test. Py-
'Najnowsze wieści z pola') lons, swój system testów jednostkowych oparł
b.save() o nose, a Django o doctest i unittest, dodając
#edycja dodatkowo własny system do testowania ele-
b.name='Blog Zbyszka' mentów kodu powiązanego z bazą danych (fi-
b.save() xtures). Można również stosować aplikacje ta-
# pobranie wszystkich blogów kie jak Selenium.
blogi = Blog.objects.all()
# pobranie 5 blogów Podsumowanie
blogi = Blog.objects.all()[:5] Powyższy artykuł miał za zadanie przybliżyć
# filtrowanie i sortowanie wyników programistom PHP alternatywne rozwiąza-
wpisy = Entry.objects.filter( nia, jakie można wykorzystać przy tworzeniu
pub_date__year=2005).order_by( stron internetowych. Zarówno PHP, jak i Py-
'-pub_date', 'headline') thon, mają swoje wady i zalety, lecz oba języki
dobrze sprawdzają się w powierzonych im za-
Listing 7. Przykładowy widok wykorzystujący system użytkowników i uprawnień daniach. Jeżeli chcesz poznać nowy język o sze-
def moj_widok(request): rokich możliwościach, nie odchodząc zarazem
if request.user.is_authenticated(): od tworzenia stron www to, moim zdaniem, Py-
# zalogowany thon będzie dobrym wyborem.
else:
# niezalogowany
if request.user.is_staff and PIOTR MALIŃŚKI
request.user.has_perm( Autor jest studentem Politechniki Warszawskiej
'news.add_news'): na kierunku Technologia Chemiczna. Od 4 lat zaj-
# zalogowany, muje się tworzeniem aplikacji w PHP, jak też od
z odpowiednimi uprawnieniamibv niedawna aplikacji o Pythonie.
Kontakt z autorem: riklaunim@gmail.com

34 04/2007

You might also like