Explore Ebooks
Categories
Explore Audiobooks
Categories
Explore Magazines
Categories
Explore Documents
Categories
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
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
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.
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ę
34 04/2007