Django i jego konkurenci

Opublikowane przez Jarosław Zabiełło Wed, 21 Jun 2006 15:18:00 GMT

Po ostatnich paru tekstach o Django, pora na odrobinę odmiany, bo Django niekoniecznie musi być uważany za najlepszy framework w klasie środowisk “railsopodobnych”. :)

TurboGears

Trzeba pochwalić dobry marketing megaframeworku1 TurboGears, bo już w Amazonie jest nawet dostępna książka na jego temat. Jednakże, małe to pocieszenie. TurboGears raczej nie będzie poważną alternatywą dla Django z prostej przyczyny. Cały jego kręgosłup opiera się na mało profesjonalnej implementacji frameworka CherryPy. Na ten temat było sporo dyskusji na grupie pl.comp.lang.python, więc nie będę się powtarzał.

Pylons

O Pylons pisałem wcześniej ale nie w kontekście Django. Moim zdaniem, Pylons jest jedynym frameworkiem, który aktualnie może stanowić być realną alternatywę dla Django.

Wpierw trzeba napisać kilka słów wyjaśnienia dla tych, co myślą że Pylons to jakiś taki zlepek innych bibliotek i frameworków jak TurboGears. Pylons to właściwie nic innego jak framework Myghty tylko, że ze znacznie większym przełożeniem akcentów na paradygmat MVC i podobieństwo do będacych aktualnie “na fali” Railsów.

Twórcy Myghty, mimo bardzo dobrej implementacji i wydajności nie mogli wcześniej przebić się do miłośników Pythona ze względu na zbytnie podobieństwa do Perla (nic dziwnego, Myghty był wzorowany na bardzo dobrym perlowym Masonie, który jest używany na dosyć dużą skalę)

Postanowiono więc troszkę dostosować Myghty dla ludzi lubiących prostotę Pythona i elegancję Ruby on Rails. I tak powstał Pylons.

Zalety Pylonsów.

Myghty pozwala praktycznie na wymianę wszystkich swoich “podzespołów”. W wypadku Pylonsów, użyto resolvera adresów URL opartego na bibliotece Routes. W skrócie można powiedzieć, że Pylons jest tu prawie identyczne jak Rails. “Prawie”, bo Routes jest potężniejszym resolverem od tego co mają Railsy (pozwala np. na używanie większych uogólnień i wyrażeń regularnych).

Elastyczność

Elastyczność Pylonsów jest znacznie większa od Django. W praktyce tam, gdzie stosuje się wstawki PHP do profesjonalnych systemów CMS takich jak RedDot, Pylons dzięki swojej elastyczności i potędze szablonów Myghty znacznie łatwiej może wyprzeć tu PHP. Django jest systemem znacznie bardziej monolitycznym. To jest jego zaletą ale równocześnie także i wadą w wypadkach kiedy potrzebujemy znacznie większej elastyczności.

DRY w kontekście generowania adresów URL

Przewagą korzystania z Routes jest nie tylko prostota budowania adresów url bez konieczności posiadania wiedzy o wyrażeniach regularnych. Największą zaletą jest stosowanie helperów do budowania adresów URL. Identycznie jak w Railsach, jakakolwiek zmiana zasady rozwiązywania adresów, automatycznie przemapuje wszystkie adresy http we wszystkich szablonach. W wypadku Django musimy mozolnie poprawiać wszystkie szablony. W wypadku dużego serwisu jest to kupa, niepotrzebnej roboty2.

Ajax i cała reszta helperów z Ruby on Rails.

Django (jak dotąd) nie posiada wbudowanej implementacji Ajax’a. Nie ma nawet jednomyślności jaką bibliotekę do tego celu mieliby użyć3. Poza tym Pylons implementują wiele z helperów jakie mają Rails dostępne dla swoich szablonów.

Potęga szablonów Myghty

Jeśli komuś przeszkadzają małe możliwości szablonów Django (celowo takie są, bo są kierowane do nieprogramistów) to możliwości jakie dają szablony Myghty są po prostu powalające. Jeśli ktoś mówi, że Django ma dobry cache, to niech się przyjrzy temu co potrafią wykorzystywane w Pylons – szablony Myghty.

Każdy szablon może być komponentem niezależnie keszowanym wg bardzo wyrafinowanych zasad (potężniejszych od tych, co oferuje Django) Regeneracja cache jest także inteligentnie napisana (podobnie jak to robi Skunkweb) Tzn. nigdy nie ma sytuacji, kiedy nadchodzi żądanie wyświetlenia strony i w tym samym momencie trzeba odświeżyć cache (bo się np. przeterminował). Pylons w takim wypadku, odwleka operację odświeżania cache’a i podaje starą zawartość. Regeneracja następuje zaraz za tym requestem. W efekcie nigdy nie ma żadnych “czkawek” w takiej krytycznej sytuacji.

Jeśli ktoś myśli, że to bardzo rzadki przypadek, to niech sobie wyobrazi czy co się dzieje w wypadku naprawdę dużego obciążenia serwera. Pylons/Myghty był od początku tworzony z myśla pracy w sytuacji mocno obciążonego serwera.

Szablony Myghty obsługują nie tylko bardzo potężne mechanizmy includowania (tzn. można przekazać wiele różnych parametrów do includowanego szablonu włącznie z indywidualnymi zasadami keszowania). Myghty obsługują także mechanizm dziedziczenia4.

Automatyczne generowanie dokumentacji.

Pylonsy pozwalają na automatyczne generowanie dokumentacji z projektu. Wykorzystuje do tego celu pythonowe docstringi i zamiast HTML – reStructuredText (które są częścią projektu docutils)

Zapakowanie projektów do uniwersalnego formatu .egg.

Pylonsy potrafią zapakować cały projekt do paczki .egg co umożliwia bardzo łatwą dystrybucję aplikacji pylonsowych. Django tej (jakże pożytecznej) opcji w ogóle nie ma zaimplementowanej!

Zalety Django.

Mimo powyższych zalet Pylonsów, Django ma także kilka swoich, dobrych stron.

Lepsza dokumentacja.

Dzięki swojej monolityczności, Django dysponuje znacznie pełniejszą dokumentacją i jest ona zgromadzona w jednym miejscu. W wypadku Pylonsów dokumentacja jest niezbyt wyczerpująca i porozrzucana. Wynika to w głównej mierze z tego, że Pylons używa gotowych komponentów z innych projektów.

Świetna obsługa formularzy.

Django pracuje na wyższym poziomie abstrakcji odnośnie pracy z formularzami. O ile nie potrzebujemy większej elastyczności, to tą kwestię mają doskonale zaprojektowaną. Jeśli chcemy czegoś więcej, możemy przeciążyć metody jakie używa Django i wzbogacić je w dodatkowe opcje (np. obsługę zdarzeń javascript). Django obsługuje bardzo elegancko walidację formularzy. Pylons TurboGears też) korzysta z FormEncode, ale wydaje mi się, że Django jest tu jeszcze prostsze.

ORM

Djangowy korzysta z własnego ORM (mapera relacyjno-obiektowego) Pylons korzysta z SQLObject. Oba ORM’y są podobne, ale mnie się bardziej podoba ten, co ma Django. Moim zdaniem ma bardziej elegancką składnię. Ma także lepszą dokumentacje. Trochę to dziwne, bo SQLObject nie jest wcale nowym projektem. Mogliby się postarać o lepszą dokumentację, bo ta co jest, jest fatalna.

Panel admina.

To jest wizytówka Django. O ile nie potrzebujemy bardzo specyficznego jego działania, to jest bardzo pomocny. To nie jest żaden “scaffolding” z Railsów. To dopracowana aplikacja końcowa.

Generic views

To kolejna wizytówka Django. Za pomocą konfiguracji adresów (w pliku urls.py) i generic views można budować całe serwisy bez tworzenia ani jednego kontrolera. W ten sposób działa cała strona domowa Django. Osobiście głęboko nie wchodziłem w działanie tych mechanizmów, ale wyglądają bardzo interesująco i mogą daćo gromne przyśpieszenie w budowaniu stron www.

Szersze wdrożenia i silniejsze wsparcie komercyjne.

Django może się poszczycić niezła listą poważnych wdrożeń. Skala złozoności portalów zbudowanych w Django przewyższa to, czym się chwali strona domowa Railsów. Jeśli chodzi o Pylons, to wdrożeń jest bardzo mało. Może brakuje im trochę zmysłu marketingowego jaki mają twórcy Railsów i Turbogears? Na pewno brakuje lepszej, obszerniejszej dokumentacji wraz z większą ilością przykładów.

Na bazie Django oferowany jest także odpłatnie, komercyjny CMS (system zarządania treścią) – Ellington. Specjalizowany jest do większych serwisów, gazet itp. Firmy ceniące sobie wsparcie komercyjne, nie muszą się więc obawiać, że Django to jakiś projekt paru zapaleńców.

Django w rzeczy samej, jest projektem który został wyekstraktowany z komercyjnego projektu Ellington.

No i na koniec, last but not least, twórcom Django udało się pozyskać sympatię samego twórcy języka Pythona – Guido van Rossum’a. Na stronie głównej. Pythona w sekcji Web programming, obok Zope widzimy Django i Turbogears…

Podsumowanie.

Django ma swoje zalety, ale nie jest wolny od wszelkich wad. Jednakże, ogólnie rzecz biorąc, to dobry framework, który raczej nie powinien mieć trudności w zdominowaniu dziedziby budowania aplikacji internetowych w Pythonie.

Jednak tam, gdzie liczy się większa elastyczność i gdzie monolityczność Django jest nie do zaakceptowania, głównym moim faworytem jest Pylons. To jedyna realna alternatywa dla Django5.

-

1 Megaframework – środowisko zbudowane z gotowych, innych rozwiązań. Turbogears korzysta m.in. z frameworku CherryPy, szablonów Kid, SQLObject jako ORM (mapera relacyjno obiektowego).

2 Developerzy Django są przyciskani do muru żądaniami aby wprowadzić jakiś mechanizm zastępujący ręczne wpisywanie adresów, i nie wykluczają, że użyją Routes jako alternatywnego resolvera URL. Ale nie wiadomo kiedy i czy w ogóle to zrobią.

3 Nie wiem dlaczego nie chca użyć gotowych bibliotek jakie już używa Pylons. Po co odkrywać na nowo koło?

4 Dziedziczenie działa trochę inaczej niż w Django i Cheetah. Np. nie ma tu, tak wygodnych “bloków” do przeciążania. Ale jest za to coś, co przypomina “akwizycję” znaną z Zope. Tzn. w Myghty można wrzucić do folderu z szablonami plik “autohandler” i automatycznie staje się szablonem bazowym dla wszystkich szablonów (bez dotykania ich zawartości!) To pozwala na wygodne zarządzanie całymi grupami szablonów.

5 Poza oczywiście Zope czy Plone, ale to jest trochę inna bajka i temat na oddzielne rozważania. :)

Posted in ,  | Tagi , ,  | 1 comment

Django - zabójcza aplikacja. Część III.

Opublikowane przez Jarosław Zabiełło Mon, 12 Jun 2006 20:29:00 GMT

W części pierwszej i drugiej opisałem podstawowe zalety Pythona i Django. Pora ma malutką demonstrację działającej aplikacji. Będzie to mała, ale poręczna wyszukiwarka biblijna (choć kod można łatwo zaadoptować do innych treści rzecz jasna). Jako bazę użyję MySQL5. Zakładam także, że docelowo projekt będzie chodził pod Linuksem. Natomiast będzie budowany i testowany pod Windowsami. Taki model pracy jest często spotykany. Django oczywiście w wersji 0.95 SVN, czyli wersji pozbawionej wcześniejszej “magii” (kod Django jest teraz bardziej jawny i oparty na standardowych mechanizmach Pythona)

Zaczynamy!

Na początku musimy stworzyć projekt oraz aplikację (Django w ramach jednego projektu potrafi obsługiwać wiele aplikacji)

admin-django startptoject myproject
cd myproject
manage.py startapp biblia

Zauważmy, że skrypt admin-django uruchamiamy tylko raz. Potem już posługujemy się skryptem manage.py. Dzięki temu odpada nam kombinowanie z definiowaniem zmiennej systemowej DJANGO_SETTINGS_MODULE. Listę wszystkich dostępny opcji, zarówno dla django-admin.py jak i manage.py, uzyskamy uruchamiając te skrypty bez żadnego parametru.

Wstępna konfiguracja.

Mamy zatem stworzony katalog z projektem i aplikacją. Wpierw trzeba skonfigurować plik settings.py2. Na początku pliku ustawiamy:
import sys

if sys.platform == 'win32':
    DEBUG = True
else:
    DEBUG = False
TEMPLATE_DEBUG = DEBUG

ADMINS = (
    ('Administrator', '[email protected]'),
    )

MANAGERS = ADMINS

DATABASE_ENGINE = 'mysql'
DATABASE_NAME = 'myproject' 
if sys.platform == 'win32':
    DATABASE_USER = 'root'
    DATABASE_PASSWORD = ''
else:
    DATABASE_USER = 'user_na_linuksie'
    DATABASE_PASSWORD = 'haslo_pod_linuksem'

if sys.platform == 'win32':
    DATABASE_HOST = '' # domyslnie bedzie localhost
else:
    # pod linuksem zwykle korzystamy z szybkiego gniazda unix
    DATABASE_HOST = '/var/run/mysqld/mysqld.sock'
DATABASE_PORT = '' # czyli domyślnie będzie 3306

ENABLE_PSYCO = False

Kilka istotnych uwag.

  • Adres mailowy admina nie jest taki zupełnie nieistotny. W wypadku kiedy aplikacja na serwerze produkcyjnym się wyłoży na jakimś wyjątku, na ten adres jest automatycznie wysyłany mail z wszystkimi szczegółami. Trudno śledzić, czy w którymś momencie aplikacja się nie wywali. Django zadba, aby żaden taki wypadek nie umknął naszej uwadze1.
  • Należy sobie ustawić odpowiednie hasła dostępu do MySQL5 pod windozą i pod linuksem.
  • Ważne jest, aby wyłączyć obsługę akceleratora Psycho. To jeszcze nie jest dobrze przetestowane. Jak to miałem włączone, to pod Linuksem miałem problemy z działaniem djangowego panelu admina.
  • Musimy ręcznie sobie stworzyć (jeśli tego nie zrobiliśmy) bazę. Django za nas bazy nie stworzy. W naszym przypadku, tabelkę na której będziemy pracować mam już gotową w bazie. Tu jest jej spakowany dump który trzeba sobie załadować.

Pozostałe ustawienia:

LANGUAGE_CODE = 'pl' # domyślnie był angielski
#... 
if sys.platform == 'win32':
    MEDIA_ROOT = r'H:/home/myproject/biblia/public'
else:
    MEDIA_ROOT = r'/home/myproject/biblia/public'
#... 
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'myproject.biblia',
)

Do słownika INSTALLED_APPS musimy dodać naszą aplikację aby można było jej używać. Mówi o tym ostatnia linijka powyższego kodu. Zmienna MEDIA_ROOT musi być bezwzględną ścieżką do plików statycznych. Pod serwerem www odpowiada to zmiennej DOCUMENT_ROOT, czyli miejsca od którego serwer www cokolwiek widzi.

Interaktywne testowanie Django z poziomu konsoli.

W każdej chwili możemy odpalić interaktywny dostęp do środowiska Django za pomocą komendy:
manage.py shell
Warto sobie wcześniej zainstalować ipythona, bo Django domyślnie próbuje uruchomić jego zamiast standardowy interpreter. Dzięki ipythonowi mamy wspaniałe uzupełnianie metod do obiektów + historia wczesniejszych operacji, która nie znika wraz z zamknięciem ipythona.

Serwer.

Możemy odpalić wbudowany serwer www za pomocą komendy:

manage.py runserver

Domyślnie serwer się podniesie pod adresem http://127.0.0.1:8000. Można zmienić zarówno port jak i adres jak ktoś chce, rzecz jasna. Odpal manage.py (bez parametrów) to się dowiesz, jak.

ORM

No dobrze, pora na coś bardziej interesującego. Django operuje na relacyjnej bazie danych za pomocą swojego ORM (mapera relacyjno-obiektowego) Zalet takiego podejścia jest wiele. Wspomnę tylko o tym, obiektowo można znacznie lepiej opisać dane modelu biznesowego niż to zrobić może czysty SQL ze swoimi kluczami obcymi i trigerami. Django wymaga aby w pliku myproject/biblia/models.py zdefiniować dane dla ORM’a. Zasada jest prosta: klasa odpowiada tabeli, a atrybuty klasy – jej polom. Aby jednak sobie uprościć życie, można posłużyć się skryptem manage.py.

Poniższy skrypt robi introspekcję bazy i wygeneruje pythonowe definicje wszystkich jej tabel. Jako parametr podajemy nazwę naszej aplikacji (mówiłem że Django jest zbudowane do pracy z wieloma aplikacjami w ramach projektu) Możemy spokojnie zamazać plik models.py bo po stworzeniu projektu nic tam szczególnego nie ma.

H:\home\myproject>manage.py inspectdb biblia > biblia/models.py

Mamy zatem naszą wstępną obiektową definicję dla nasej tabelki:

from django.db import models

class BibliaGdanska(models.Model):
    id = models.IntegerField(primary_key=True)
    ref = models.CharField(unique=True, maxlength=9)
    chapter_nr = models.IntegerField(unique=True)
    verse_nr = models.IntegerField(unique=True)
    verse = models.TextField()
    class Meta:
        db_table = 'biblia_gdanska'

Może sprawdźmy, czy to działa za pomocą interaktywnej konsoli:

H:\home\myproject>manage.py shell
Deleting alias <dir>, it's a Python keyword or builtin.
Python 2.4.3 (#69, Apr 11 2006, 15:32:42) [MSC v.1310 32 bit (Intel)]
Type "copyright", "credits" or "license" for more information.

IPython 0.7.1.fix1 -- An enhanced Interactive Python.
?       -> Introduction to IPython's features.
%magic  -> Information about IPython's 'magic' % functions.
help    -> Python's own help system.
object? -> Details about 'object'. ?object also works, ?? prints more.

In [1]: from myproject.biblia.models import BibliaGdanska
In [2]: BibliaGdanska.objects.count()
Out[2]: 31151L

Bingo! Widać, że działa.

Kontroler i szablon.

Teraz pora na naszą aplikację internetową. Musimy stworzyć kontroler. Z tajemniczych powodów developerzy Django zamiast MVC (model-view-controller) stosują nazwę MTV (model-template-view). W każdym razie, to co zwykle nazywamy kontrolerem oni nazywają widokiem (view) a to co nazywamy widokiem, oni nazywają szablonem. Mniejsza o nazwy. Kontroler tworzymy w pliku myproject/biblia/views.py

#-*- coding: utf-8 -*-

from django.shortcuts import render_to_response

def home(request):
    return render_to_response('home.html')

Plik home.html jest szablonem. Stwórzmy na razie ten plik z napisem “alama kota” w środku, aby zobaczyć, czy to działa. Plik powinien leżeć w myproject/biblia/templates/home.html.

Rozwiązywanie adresów URL

Wpierw musimy powiedzieć Django aby wiedział, gdzie ma szukać naszego kontrolera. W tym celu dodajmy taką treść do pliku myproject/biblia/urls.py

from django.conf.urls.defaults import *
from settings import DEBUG, MEDIA_ROOT

urlpatterns = patterns('',
    (r'', include('myproject.biblia.urls')),
    #(r'^admin/', include('django.contrib.admin.urls')),
)

if DEBUG:
    urlpatterns += patterns('',
        (r'^images/(?P<path>.*)$', 'django.views.static.serve', {'document_root': MEDIA_ROOT+'/images', 'show_indexes': True}),
        (r'^stylesheets/(?P<path>.*)$', 'django.views.static.serve', {'document_root': MEDIA_ROOT+'/stylesheets', 'show_indexes': True}),
        (r'^javascripts/(?P<path>.*)$', 'django.views.static.serve', {'document_root': MEDIA_ROOT+'/javascripts', 'show_indexes': True}),
    )    

Powyższy kod robi kilka rzeczy.

  • Wiąże domyślną stronę z naszym projektem. Wejście na http://127.0.0.1:8000/ przekaże sterowanie do pliku myproject/biblia/urls.py (który za chwilkę stworzymy).
  • Takie podejście powoduje że każda aplikacja może posiadać swoje niezależne zasady rozwiązywania adresu url. Dlatego oddelegowujemy obsługę URL’i do pliku urls.py wewnątrz naszej aplikacji.
  • Zakomentowaną linijkę z panelem admina na razie zostawmy, wrócę do tego później.
  • Ostatnie linijki są potrzebne do tego, aby Django obsługiwał nie tylko plik Pythona ale także obrazki, style kaskadowe i skrypty języka JavaScript. Przyjąłem (wzorując się na Railsach) że są one odpowiednio w folderach myproject/biblia/public/images, myproject/biblia/public/stylesheets i myproject/biblia/public/javascripts.
  • Dlaczego ten kod jest dostępny tylko dla DEBUG=True? Ano dlatego, że do pracy developerskiej pod windozą nie potrzebujemy żadnego Apache’a ani Lighttpd. Wystarczy wbudowany serwer www jaki dostarcza Django. Natomiast na serwerze produkcyjnym, gdzie chcemy uzyskać największą wydajność, lepiej aby te pliki podawał serwer www i Django się tego nie dotykało. Tak będzie najlepiej i najszybciej.

Pozostał do skonfigurowania plik myproject/biblia/urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('myproject.biblia.views',
    (r'^$', 'home'),
   #(r'^admin/', include('django.contrib.admin.urls')),
)

Tu również mamy zakomentowany panel admina. Zostawmy go na razie w spokoju. Można uruchamiać: http://127.0.0.1:8000/ powinno wyświetlić nasz szablon z treścią “ala ma kota”. No to może lepiej aby wyświetlić coś bardziej atrakcyjnego. Zbudujmy formularz.

Formularz

Formularze są zmorą większości programistów. Są upierdliwe w obłudze, walidacji i co gorsze, ciągle z nimi mamy do czynienia. Aby ułatwić nam życie, Django stosuje specjalną technikę tzw. manipulatorów, aby praca z formularzami była miła i przyjemna. Muszę przyznać, że to była jedna z ważniejszych rzeczy, jaka mnie przyciągnęła do Django. Pylons i Rails mają swoje helpery, ale nie są one aż tak wygodne jak to, co oferuje Django3.

Zobaczmy jak się używa manipulatora. Wpierw zmieńmy nasz szablon (plik: myproject/biblia/templates/home.html). Będzie to prosty formularz z jednym polem gdzie wpiszemy wyszukiwane słowo.

<form method="get" action="">

    {% if form.q.errors %} 
        <div class="formError">
          Wpisz frazę o długości min. 3 znaków.
        </div>
    {% endif %}

    {{ form.q }}
    <input type="submit" value="szukaj" />

</form>

Manipulator.

Teraz pora na manipulator. Musimy stworzyć plik myproject/biblia/manipulators.py o przykładowej treści:

import re
from django import forms
from django.core import validators

class SzukajManipulator(forms.Manipulator):
    def __init__(self):
        regex = re.compile(r'(\w{3,})', re.U)
        self.fields = (
            forms.TextField(
                field_name='q',
                length=30,
                maxlength=255,
                is_required=True,
                validator_list=[validators.MatchesRegularExpression(regex)]
                ),
            )

Teraz zepnijmy wszystko razem w djangowym widoku (naszym kontrolerze). Zmieńmy treść pliku myproject/biblia/views.py na:

#-*- coding: utf-8 -*-

from django.shortcuts import render_to_response
from django import forms
from manipulators import SzukajManipulator
from models import BibliaGdanska

def home(request):
    recordset = []
    errors = _GET = {}
    manipulator = SzukajManipulator()
    # tworzę kopię parametrów przekazanych z formularza
    _GET = request.GET.copy()
    if request.GET:
        # sprawdzam czy formularz nie ma błędów
        errors = manipulator.get_validation_errors(_GET)
        if not errors:
            manipulator.do_html2python(_GET)
           # wyszukuję cytaty 
           recordset = BibliaGdanska.objects.all().filter(verse__icontains=_GET['q'])
    form = forms.FormWrapper(manipulator, _GET, errors)
    return render_to_response(
        'home.html',
        {'request': request,
         'form': form,
         'recordset': recordset,
         'hits': len(recordset)})

Wyświetlenie wyników.

Aplikacja działa4, ale nie widać wyników. Wyniki wyświetlimy w tym samym szablonie. Teraz będzie wyglądał tak:

<form method="get" action="">
    {% if form.q.errors %} 
        <div class="formError">
          Wpisz frazę o długości min. 3 znaków.
        </div>
    {% endif %}    
    {{ form.q }}
    <input type="submit" value="szukaj" />   
</form>

{% if recordset %}
    <div>
      Znaleziono <b>{{ hits }}</b> wersetów:
    </div>
    <ol>
    {% for row in recordset %}
        <li>
            {{ row.ref}} {{ row.chapter_nr}}:{{ row.verse_nr }} 
            &quot;{{ row.verse }}&quot;
        </li>
    {% endfor %}
    </ol>
{% else %}
    Nie znaleziono wersetów dla frazy {{ request.GET.q }} :(
{% endif %}

Program powinien działać. Jednak w wypadku znalezienia mniej niż 5 wersetów niezbyt po polsku zabrzmi wynik, np. “Znaleziono 1 wersetów”. W wypadku języka angielskiego możemy zmodyfikować ten fragment szablonu za pomocą modyfikatora pluralize5. Polski jezyk jest jednak znacznie bardziej wyrafinowany od angielskiego, bo używa 2 różnych form dla liczby mnogiej: 1 werset, 2 wersety, 5 wersetów. Na szczęście możemy sobie zmienić sposób pracy tego modyfikatora.

Przeciążene modyfikatora

Aby nadpisać istniejący modyfikator lub dodać nowy, własny, należy stworzyć wpierw folder myproject/biblia/templatetags z pustym plikiem o nazwie init.py. Dodajemy tam drugi plik, o nazwie, powiedzmy: plugins.py o następującej treści:

import re, sys
from django import  template

register = template.Library()

@register.filter(name='pluralize')
def pluralize(value):
    """Polish implementation"""
    try:
        if int(value) in (2,3,4):
            return 'y'
        elif int(value) >= 5:
            return '\xc3\xb3w' # utf8
    except ValueError: # invalid string that's not a number
        pass
    except TypeError:
        try:
            if int(value) in (2,3,4):
                return 'y'
            elif int(value) >= 5:
                return '\xc3\xb3w' # utf8            
        except TypeError: 
            pass
    return ''

Zamiast polskiego znaczka ó, użyłem zapisu ’\xc3\xb3’ bo to wartość utf-8 i taki zapis jest niezależny od tego, w czym otworzymy plik. Nikt przypadkowo nie popsuje nam polskich ogonków.

Aby to zadziałało, musimy gdzieś na początku w szablonie dodać linijkę, która załaduje nam nową definicję modyfikatora pluralize.

{% load plugins %}

Kontekst i dziedziczenie szablonów.

Nasz kod działa, ale kod HTML jest daleki od doskonałości. Dobrze byłoby dodac jakiś nagłówek, stopkę itp. Django skopiowało z pythonowych szablonów Cheetah bardzo ciekawy sposób tworzenia kolejnych szablonów za pomocą obiektowego przeciążania starych.

Stwórzmy nasz szablon bazowy (myproject/biblia/templates/base.html)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>Przykład aplikacji w Django</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>    
         <h3>Wyszukiwarka Biblii Gdańskiej</h3>
         <h4> (przykład aplikacji w Django)</h4>
          <div id="main">
          {% block main %}
              tutaj będzie jakaś nowa treść   
          {% endblock %}
          </div>
        <hr size="1" />
        <div>
        &copy; 2006 
        <a href="http://blog.zabiello.com">Jarosław Zabiełło</a>. 
        </div>
    </div>
</body>
</html>

Ostatecznie szablon home.html będzie więc wyglądał tak:

{% extends "base.html" %}

{% load plugins %}

{% block main %}

<form method="get" action="">
    {% if form.q.errors %} 
        <p class="formError">Wpisz frazę o długości min. 3  "znaków".</p>
    {% endif %}    
    {{ form.q }}
    <input type="submit" value="szukaj" />   
</form>

{% if recordset %}
    <div>Znaleziono <b>{{ hits }}</b> werset{{ hits|pluralize }}:</div>
    <ol>
    {% for row in recordset %}
        <li>
            {{ row.ref}} {{ row.chapter_nr}}:{{ row.verse_nr }} 
            &quot;{{ row.verse }}&quot;
        </li>
    {% endfor %}
    </ol>
{% else %}
    <p>Nie znaleziono wersetów dla frazy <b>{{ request.GET.q }}</b></p>
{% endif %}

{% endblock %}

Szablon oparty na innym szablonie implementuje dowolne bloki z poprzedniego. Cały pozostały kontekst jest automatycznie dziedziczony. Takie podejście bardzo skraca wielkość szablonów i czyni je jeszcze bardziej czytelnymi.

Podświetlanie szukanej frazy.

Do pliku plugins.py gdzie wcześniej zmieniliśmy definicję modyfikatora pluralize, dodajmy kolejny. Będzie nam podświetlał w wersetach to, co szukamy.

@register.filter(name='highlight')
def highlight(s, q):
    if not isinstance(s, unicode): 
        s = unicode(s, 'utf-8')
    s = re. compile('('+re.escape(q)+')', re.U|re.I).sub(r'<strong class="highlight">\1</strong>', s).encode('utf-8')
    return s    
W środku zastosowano sztuczkę z przełączeniem się na obiekty Unicode, aby mieć pewność że polskie ogonki duże i małe będą tak samo traktowane. W szablonie home.html wystarczy zmienić jedną linijkę:
{{ row.verse|highlight:request.GET.q }}

Co dalej?

Mam nadzieję, że artykuł przybliżył trochę praktyczną stronę uzywania Django. To dobry i szybki framework. Przykładowe serwisy jakie w nim napisano są znacznie bardziej skomplikowane i większe niż te, co widać na stronie Rails. Django został napisany do szybkiego tworzenia całkiem sporych serwisów

W kolejnym artykule, pokażę jak sobie wygodnie skonfigurować panel admina który udostępnia Django. Panel admina nie jest żadnym prostym rusztowaniem (scaffolding) do modyfikacji bazy. To kompletna aplikacja dla użytkownika końcowego. Bardzo wygodna i łatwa w użyciu. Panel Django jest kolejną z jego cech, która daje mu wyraźną przewagę w stosunku do konkurencji.

-

1 Kompletnie inaczej od 99% aplikacji pehapowych, gdzie o błędach dowiadujemy się najczęściej dopiero wtedy, jak wszystko leży, albo jak ktoś łaskawie nas poinformuje.

2 Jak widać, to normalny plik Pythona. Żadne chore XML i inne formaty nie są w ogóle nam potrzebne – Python jest wystarczająco dobry, aby łatwo i przyjemnie prezentować zagnieżdżone struktury. Inne języki, jak np. Java nie zbyt dobrze nadają się do takich rzeczy, dlatego muszą posiłkować się XML.

3 Tzn. Railsy się już poprawiły, bo jest plugin który dodaje im taką samą funkcjonalność jak Django. Nazywa się active-form i można go zainstalować prosto spod RadRails’a.

4 Kto nie wierzy, niech sobie wpisze print recordset po operacji wyszukiwania. Na konsoli serwera www wyświetli mu się zawartość tej zmiennej.

5 Szablony Django korzystają ze składni modyfikatorów podobnych do pehapowych Smartów.

Posted in ,  | Tagi  | 8 comments

Django na Lighttpd + FastCGI

Opublikowane przez Jarosław Zabiełło Wed, 31 May 2006 21:16:00 GMT

Okazuje się, że uruchomienie Django na serwerze Lighttpd i FastCGI nie jest wcale trudne. Taki zestaw pożera znacznie mniej zasobów komputera niż Apache i mod_python. Efekt dostępny jest tutaj. Projekt Django został stworzony w /home/django_project. Użyłem Django w wersji SVN (pozbawionej “magii”), MySQL 5, Python 2.4.3 oraz system to Debian 3.1. Cała konfiguracja to:

Plik lighttpd.conf (aktualny):

$HTTP["host"] == "koran.apologetyka.com" {
  server.document-root = "/home/django_project/koran/public"
  url.rewrite-once = (
    "^/(media|stylesheets|images|javascripts).*" => "$0",
    "^/admin/(.*)$" => "/django-admin.fcgi/admin/$1",
    "^/(.*)$" => "/django.fcgi/$1"
  )
  fastcgi.server = (
    "/django.fcgi" => (
      (
        "bin-path" => "/home/django_project/django.fcgi",
        "socket" => "/tmp/django.sock",
        "check-local" => "disable",
        "min-procs" => 1,
        "max-procs" => 1,
      )
    ),
    "/django-admin.fcgi" => (
      (
        "bin-path" => "/home/django_project/django-admin.fcgi",
        "socket" => "/tmp/django-admin.sock",
        "check-local" => "disable",
        "min-procs" => 1,
        "max-procs" => 1,
      )
    )
  )
  server.error-handler-404 = "/django.fcgi"
}
Plik django.fcgi:
#!/usr/local/bin/python2.4
import os, sys
sys.path += ['/home'] 
from flup.server.fcgi import WSGIServer
from django.core.handlers.wsgi import WSGIHandler
os.environ['DJANGO_SETTINGS_MODULE'] = 'django_project.settings'
WSGIServer(WSGIHandler()).run()

Później opiszę dokładniej sam kod Django.

Posted in  | Tagi , ,  | 4 comments

Django - zabójcza aplikacja. Część II.

Opublikowane przez Jarosław Zabiełło Sat, 27 May 2006 16:53:00 GMT

Jak wspomniałem w pierwszej części, Django jest frameworkiem który wyrósł na bazie zastosowań komercyjnych. Zanim twórcy zdecydowali się otworzyć i udostępnić jego kod na zasadach open-source, Django był już wcześniej intensywnie używany w zastosowaniach komercyjnych1.

Przewaga Django

Wcześniej pisałem o zaletach Pylonsów. Jednakże, po moich ostatnich testach z “oczyszczoną z magii” wersją Django muszę przyznać, że jest to chyba aktualnie najlepszy framework, z jakim miałem do czynienia w tej klasie zastosowań.

Django oferuje znacznie więcej helperów i udogodnień niż świetny Pylons. Poza wbudowaną autoryzacją i zaawansowanym panelem admina, Django pracuje na wyższym poziomie abstrakcji niż Pylons czy Rails. Zamiast prostych generatorów HTML dla formularzy, Django wprowadza kontrolki, które pracują na wyższym poziomie abstrakcji. Bardzo przejrzyście obsługuje także walidowanie formularzy. Kto się męczył z obsługa formularzy, nareszcie odetchnie z ulgą. Idea manipulatorów bardzo upraszcza pisanie obsługi formularzy. Ktoś powie, że to można sobie samemu napisać. Owszem. Ale Django daje ci to już gotowe. Uruchamiasz i używasz zamiast tracić czas.

Sprawa dokumentacji, i promocji w ogólności, w wypadku wiekszości frameworków Pythona jest po prostu żenująca. Zdumiewające jest jak to jest możliwe, że nawet tak potężne środowisko jakim jest Zope ma tak słabą stronę i chaotycznie porozrzucaną dokumentację.

Kilka mądrych posunięć.

Pierwszą, mądrą rzeczą, jaką zrobiono po otwarciu kodu Django, było skupienie się na pisaniu dokumentacji. Dzięki temu, Django ma dziś jedną z najlepszych dokumentacji pomiędzy pythonowymi frameworkami. Bez dobrej dokumentacji, trudno aby ktokolwiek się zainteresował projektem. Dokumentacja Django nie równa się jeszcze temu co jest dostępne dla Railsów ale jest i tak lepsza od większości frameworków pythonowych.

Drugim, równie dobrym posunięciem, był refaktoring pierwotnego kodu zgodnie z zasadami filozofii Pythona. Wg zasady, ze działanie jawne jest lepsze od domyślnego, nastąpił proces usuwania “magii” z kodu. Np. teraz zamiast tajemniczych prefiksów do nazw dodatkowych metod modelu, można tworzyć je bardziej naturalnie – jako metody klasowe Pythona. Aktualnie wersja pozbawiona “magii” jest dostępna w repozytorium SVN. Frameworkiem, który jest mocno przeładowany “magicznymi” metodami jest Rails. Może to i ładnie wygląda, ale filozofia Python potępia takie podejście, gdyż to utrudnia programiście w szybkim zorientowaniu się o co chodzi w kodzie.

Trzecim, dobrym pomysłem, jest możliwości testowania środowiska w sposób interaktywny w interpreterze. Domyślne uruchomia się to w miejscu stworzonego projektu za pomocą komendy: manage.py shell. Ta komenda odpala ipythona (ile mamy go zainstalowanego) i udostępnia w nim łatwy dostep do całego środowiska Django, jego modeli, bibliotek itp. Ipython to podrasowana wersja interpretera Pythona. Świetnie uzupełnia metody, ma dobrą historię edycji i cały szereg dodatkowych możliwości2.

Przykładem różnic w podejściu do kwestii jawności i “magii” jest inny sposób podejścia do modułów i przestrzeni nazw między Pythonem a Ruby. Python stosuje przejrzystą do bólu zasadę: moduł to po prostu plik. Wszystko co w nim jest, automatycznie jest ładowane do przestrzeni nazw określonej nazwą pliku. Python umożliwia także selektywne ładowanie z modułu wybranych klas i metod. Wszystko jest niezmiernie czytelne.

W wypadku Rubiego mamy tylko wyrażenie require które odpala i włącza plik. Przy czym z tego kodu kompletnie nic nie można wywnioskować, nawet tego, czy w środku zawiera jakikolwiek moduł. Trzeba zajrzeć aby się dowiedzieć, co zostało dorzucone do naszej przestrzeni nazw. Pythonowa zasada “jawności ponad domyślaniem się”, w tym wypadku stanowi kolejny argument na rzecz większej produktywności Pythona wobec Rubiego.

Django jest szybsze.

Django jest cholernie szybkie. Nie tylko dlatego, że korzysta z Pythona i bytecodu, ale także dlatego, że jest dobrze napisane. Np. szablony Django są szybsze od Cheetah i nie wymagają żadnej dodatkowej kompilacji! Wszystkie wyrażenia regularne używane np. do parsowania adresów URL są jednokrotnie kompilowane, są więc wykonywane bardzo szybko. Mało tego, w Django można włączyć obsługę akceleratora Psyco. Wystarczy w mojprojekt/settings.py dodać linijkę ENABLE_PSYCO = True. Railsy nie mają wydajnościowo szans z Django. Chyba tylko Pylons może się zbliżyć i nawiązać jakąś walkę na tym polu. Rails i PHP są tu bez szans.

Django pracuje na wyższym poziomie abstrakcji.

Obsługa formularzy, ich walidacja są zwykle uciążliwe i programiści mają z nimi ciągle do czynienia. Rails oraz Pylons (który to skopiował z Railsów) udostępniają cała grupę wygodnych helperów do generowania kodu html np. do formularzy. Mimo, że to jest na pewno lepsze podejście od bezpośredniego dłubania w kodzie HTML, to Django oferuje coś znacznie lepszego – kontrolki. Coś, co używa np. ASP.NET, tylko że znacznie prostsze w obsłudze.

Djangowe modele korzystające z mapowania relacyjno-obiektowego (ORM) również pracują na wyższym poziomie abstrakcji niż tylko odwzorowania prostych typów danych jakie posiada relacyjna baza danych. Uważam też, że djangowy ORM jest lepszy od SQLObject. Nie dość że ma znacznie lepszą dokumentację, to na dodatek ma więcej możliwości. Np. niby taka trywialna sprawa, ale jak w SQLObject odwzorować takie zapytanie (z takim samym traktowaniem dużych i małych polskich znaków)?

SELECT * FROM tabelka WHERE pole LIKE '%wartość%'

W Django to jest trywialna operacja i na dodatek operuje na generatorze:

for row in Tabelka.objects.filter(pole__icontains="wartość"):
    print row.pole

W kolejnych częściach, zajmę się przykładem stworzenia prostej aplikacji internetowej. Pokażę też jak przeciążyć modyfikator pluralize aby uwzględniał polskie znaki, i jak obsługiwać formularze (włącznie z dynamicznym budowaniem ich treści)

-

1 Poza całym szeregiem złożonych portali, developerzy Django sprzedają Elington – profesjonalny CMS zbudowany na bazie tego frameworku. Oczywiście Railsy również powstały pierwotnie jako projekt do zastosowań komercyjnych. Stąd nic dziwnego, że oba środowiska oferują sporo interesujących rozwiązań.

2 Aby działały uzupełniania metod (po wciśnięciu klawisza Tab) trzeba doinstalować moduł readline oraz ctypes. Jeśli interpreter nie wyrzuca wyjątku po wpisaniu import readline, to znaczy że mamy go już zainstalowanego.

(Zobacz: część III)

Posted in ,  | Tagi  | 10 comments

Django - zabójcza aplikacja.

Opublikowane przez Jarosław Zabiełło Sat, 27 May 2006 08:17:00 GMT

Muszę przyznać, że podoba mi się zarówno sposób, jak i kierunek, w którym rozwijany jest pythonowy framework Django. Nie jest to kolejny domowy projekt tworzony w ramach hobby (jak to było z CherryPy). Django powstawało od razu z założeniem pracy w ciężkim środowisku produkcyjnym. Ostatnio napisałem sobie (w ramach zabawy) pewną aplikację w Django i muszę przyznać, że praca z Django jest faktycznie komfortowa. Wyższa niż w Pylons, i wyższa nawet niż w Railsach. Aby tekst nie był za długi, podzielę go na kilka mniejszych tekstów. Przedstawię swoje spostrzeżenia co do Pythona jako języka na tle Rubiego. Potem opiszę powody dla których Django ma wielkie szanse stać się killer application dla Pythona. Oraz w kolejnych częściach opiszę krok po kroku tworzenie konkretnej aplikacji w Django. Dziś będzie krótko o Pythonie.

Przewaga Pythona

Gdy zaczynam mówić o Django, to od razu nasuwa mi się porównanie do Ruby on Rails. Django jest oparty na języku Python, a Rails na języku Ruby. Co by nie mówić o zaletach Rubiego, to Python posiada kilka cech, które moim zdaniem, stawiają go wyżej1:

Python jest szybszy.

To po prostu jest fakt i to widać gołym okiem. Python automatycznie kompiluje każdy moduł do bytecodu. To jest operacja całkowicie przezroczysta dla programisty. Bytecode przy dużym projekcie składającym się w setek plików przyśpiesza znacznie czas ładowania kodu i może od biedy służyć również jako proste zabezpieczenie źródeł. Python jest szybszy nie tylko od Rubiego, ale także od PHP. Robiłem kiedyś porównanie prostej aplikacji w mod_php5 vs Myghty. Zdziwiło mnie wtedy to, że Python był tu szybszy, bo PHP jest zoptymalizowany do szybkiego wykonywania prostych skryptów. Oczywiście, im większy kod, tym rośnie przewaga Pythona z powodu użycia bytecodu2.

Python jest łatwiejszy do nauki.

Pythona łatwiej można się nauczyć i posługiwać niż Rubiego czy nawet PHP (sic!). To jest bardzo ważny punkt, bo dotyczy kluczowej kwestii jaką jest produktywność programisty.

Filozofią Pythona jest aby było jak najmniej możliwych dróg do rozwiązania tego samego problemu. Z tego wynika, że Python stara się implementować jak najmniejszą ilość funkcji i metod. Znacznie to ułatwia poruszanie się po tych metodach. W wypadku Rubiego, nie dość, że mamy znacznie więcej metod na obiekt, to na dodatek, lista metod jest dodatkowo zaśmiecona aliasami. W Ruby mamy po kilka metod, które wykonują to samo. Po kilka konstrukcji językowych, które robią to samo. Widać tu korzenie fascynacji Perlem. Ale dla programistów to jest uciążliwość.

Python jest bardziej produktywny.

Dodatkowym czynnikiem ułatwiającym szybką prace, jest integracja prostego mechanizmu dokumentacji kodu na poziomie składni Pythona. Mowa o docstringach. W praktyce znaczy to, że prawie wszystkie edytory IDE (których jest sporo, są darmowe i są bardzo dobre jak na tę klasę języków) nie tylko rozwijają mniej metod, ale także wyświetlają ich zintegrowaną dokumentację. Efektem jest znacznie mniej czasu traconego na zaglądanie do dokumentacji czy książek. To duża, odczuwalna różnica. Mniej rzeczy do zapamiętania, podpowiedzi do składni na każdym kroku, to musi się odbijac na produktywności tworzenia kodu3.

Python ma pełną obsługę Unicode.

Pełnej obsługi Unicode nie ma ani PHP ani Ruby. Obsługują co najwyżej UTF-8 i to w ograniczonym zakresie. Np. próby konwersji znaków ze standardu cp1250 (typowa sytuacja dla polskiego serwera MSSQL) do latin2 (typowe dla serwera MySQL w internecie) skazane są na korzystanie z biblioteki iconv, co jest dosyć chorym rozwiązaniem. Chorym, bo iconv nie umie dawać sobie rady z wieloma znakami, które nie mają odpowiednika w standarcie latin2. Chodzi nie o polskie ogonki, ale o różnego rodzaju długie myślniki, polskie, dolne cudzysłowy itp.

>>> s = " „To jest jakiś tekst — spróbuj to skonwertować z cp1250 do latin2.”  "
' \x84To jest jaki\x9c tekst \x97 spr\xf3buj to skonwertowa\xe6 z cp1250 do latin2.\x94  '
>>> s = " „To jest jakiś tekst — spróbuj to skonwertować z cp1250 do latin2.”  "
>>> s
' \x84To jest jaki\x9c tekst \x97 spr\xf3buj to skonwertowa\xe6 z cp1250 do latin2.\x94  '
>>> u = unicode(s, 'cp1250')
>>> u
u' \u201eTo jest jaki\u015b tekst \u2014 spr\xf3buj to skonwertowa\u0107 z cp1250 do latin2.\u201d  '
>>> print uTo jest jakiś tekstspróbuj to skonwertować z cp1250 do latin2.”  
>>> latin2 = u.encode('iso-8859-2', 'xmlcharrefreplace')
>>> latin2
' &#8222;To jest jaki\xb6 tekst &#8212; spr\xf3buj to skonwertowa\xe6 z cp1250 do latin2.&#8221;  '

Nie chodzi tylko o konwersje znaków. Dzięki Unicode, w Pythonie możesz dokonywać rzeczy bardzo trudnych do uzyskania w PHP czy Ruby. Operacje na tekście potrafią poprawnie traktować polskie znaczki. Np. napisanie funkcji implementującej podświetlanie wyszukiwanych słów bez względy na to czy uzyto dużych, czy małych polskich znaków. Dla bazy SQL to żaden problem4 ale dla kodu?

Chcielibyśmy aby wyrażeniem regularnym podmienić jakieś słowa zawierające polskie znaczkiNp. wyrażenia regularne umieją reagować poprawnie na polskie ogonki!

#-*- coding: utf-8 -*-
import re
def highlight(tekst, slowo, encoding):
    if not isinstance(tekst, unicode):
        tekst = unicode(tekst, encoding)
    if not isinstance(slowo, unicode):
        slowo = unicode(slowo, encoding)
    replace = re.compile('('+re.escape(slowo)+')', re.I|re.U).sub
    return replace(r'<b>\1</b>', tekst)
print
print highlight("podświetl gęś GĘŚ, GęŚ", "gęś", 'cp1250') 
# => podświetl <b>gęś</b> <b>GĘŚ</b>, <b>GęŚ</b>

Jeszcze jedno. Microsoft “uszczęśliwił” nasz kilkoma standardami kodowania polskich znaków. Inny jest dla windows (cp1250) a inny dla konsoli okienka DOS (cp852). Python pozwala całkowicie zapomnieć o stringach i kodowaniach. Po prostu należy pracować na obiektach Unicode. Powtarzam: obiektach Unicode a nie stringach UTF-8, bo to nie to samo. Instrukcja print wyświetli poprawnie polskie znaki, jeśli operujemy na obiekcie unicode.

Python ma stabilniejsze i dojrzalsze biblioteki.

Przekonałem się na swojej skórze, co znaczy przekonwertować setki plików graficznych za pomocą biblioteki RMagick (Ruby), a za pomocą PIL (Python). Kod w Ruby pożarł mi cała pamięć i odmówił pracy…

-

1 Osobną kategorią jest język PHP. Właściwie szkoda gadać. Ci, co zakosztowali pracy z Pythonem i Ruby, tracą szybko zapał do mozolnego dłubania w chaotycznym, niespójnym, źle zaprojektowanym języku PHP. Na ten temat to chyba trzeba napisać oddzielny tekst. Jak znajdę czas, to sobie “poużywam” na PHP. :)

2 Aby PHP aż tak nie odstawał, trzeba użyć akcelerator. Niektóre złożone projekty PHP, jak ezPublish, bez akceleratora są koszmarnie wolne.

3 Najlepszym przykładem różnicy między Pythonem a np. .NET jest ostatnio zaimplementowany przez mnie system synchronizacji danych między serwerami. Projekt tworzony przez 6 miesięcy w VB.NET (.NET) został napisany od zera w 5 roboczych dni (z czego działający prototyp był dostępny po paru godzinach). Żeby było ciekawiej, nowy kod Pythona w tym wypadku działa i szybciej i stabilniej.

4 Np. dla MySQL (od wersji 4.1 wzwyż) trzeba tylko ustawić aby baza pracowała natywnie w utf8 (domyślnie jest latin1) i tabele oraz ich pola tekstowe miały ustawiony parametr collations na utf8_polish_ci.

(Zobacz: część II)

Posted in ,  | Tagi  | 10 comments

Guido van Rossum o szablonach Django i Cheetah

Opublikowane przez Jarosław Zabiełło Wed, 01 Feb 2006 10:03:00 GMT

Guido van Rossum (twórca języka Python) w swoim blogu przygląda się zaletom i wadom szablonów Django oraz Cheetah.

Warto przyjrzeć się dyskusji, jaka się rozpętała w blogu bo do dyskusji włączyli się developerzy Myghty, Django i Cheetah.

To, że twórca Pythona w końcu zainteresował się kwestią webowych frameworków może w końcu z gąszczu rozwiązań wyłoni wyraźnych zwycięzców. W każdym razie cieszę się że developerzy frameworków włączyli się do tej debaty. Guido pracuje teraz dla Google. Python jest jednym z 3 głównych języków jakie tam są wykorzystywane. Być może Google będzie chciało używać któregoś z frameworków.

Posted in , ,  | Tagi , ,  | brak comments

Django i AJAX

Opublikowane przez Jarosław Zabiełło Sat, 28 Jan 2006 22:13:00 GMT

Wszystko wskazuje na to, że już wkrótce Django będzie posiadać mocne wsparcie dla AJAX’a. Po namyśle, wybrano bibliotekę Dojo. Lider zespołu developerów Django ogłosił, że w ciągu nabliższych tygodni, wsparcie AJAX’a zostanie dodane do Django 0.92 Przebudowie ulegnie panel administracyjny wzbogacony o nowe możliwości biblioteki Dojo.

Posted in  | Tagi ,  | 2 comments

Guido van Rossum o frameworkach

Opublikowane przez Jarosław Zabiełło Fri, 27 Jan 2006 04:38:00 GMT

Twórca języka Python – Guido van Rossum z racji tego, że aktualnie pracuje dla Google, zainteresował się trochę więcej sprawą budowania aplikacji webowych w Pythonie. :) W swym artykule opisuje swoje wstępne wrażenia m.in. z kontaktu z Django oraz Ruby on Rails.

Zdaniem Guido, Django posiada ładny resolver adresów URL. Nie podoba mu się za to język szablonów, który zdaniem Guido jest zbyt “niepythonowy” (jakoś trudno mi sobie wyobrazić jak system szablonów może być w ogóle “pythonowy” :) No i to, że szablony Django kojarzą mu się z PHP, pokazuje że przyjrzał im się zbyt powierzchownie (ja tam nie widzę żadnego podobieństwa).

System szablonów Django jest ciekawym połaczeniem obiektowości pythonowego Cheetah i cech pehapowego Smarty. Może się podobać, lub nie, ale generalnie jest szybki i spełnia swoją rolę: jest adresowany do nieprogramistów.

Z kolei RoR posiada swój system szablonów który jest b. prosty: to po prostu połączenie Rubiego z HTML (b. podobnie do PHP czy JSP). To podejście ma także zalety jak i wady (np. trzeba znać Rubiego ale z 2-j strony nie trzeba uczyć się kolejnego pseudojęzyka do szablonów). Ostatecznie, jak komuś to nie odpowiada, to dla RoR istnieje alternatywny system szablonów zwany Liquid , system, który składnią przypomina szablony Django.

Szkoda, że Guido nie przyjrzał się bibliotece Pylons, który używa Myghty (niedawno wyszła wersja 1.0) a do rozwiązywania adresów używa b. ciekawej biblioteki – Routes.

Posted in  | Tagi , , , ,  | brak comments

Komentarz do konferencji Snakes & Rubies

Opublikowane przez Jarosław Zabiełło Thu, 19 Jan 2006 20:08:00 GMT

DHH, twórca Ruby on Rails w swoim blogu opisał różnicę między Django i RoR Generalnie podsumował swoje stanowisko, które wyraził na konferencji. Szkoda, że Adrian (ani nikt z developerów Django) nie napisał w swoim blogu żadnego komentarza. :(

Pod artykułem DHH jest sporo ciekawych komentarzy. Warto je poczytać.

Generalnie DHH został zaatakowany za niedocenianie roli umiędzynarodowienia RoR. Ludzie tego potrzebują i dobrze by było aby do RoR zostało dodane i18n. Jest kilka gotowych modułów, które do tego celu się nadają, np. Globalize (Być może DHH powstrzymuje wdrożenie i18n z powodu słabej implementacji UTF-8 (Unicode w ogólności) w Ruby? W przeciwieństwie do Rubiego Python ma wzorcową obsługę Unicode, więc wszelkie konwersje znaków nie są żadnym problemem.) Oczywiście nie ma nawet co mówić o kompletnie nędznym supporcie Unicode i UTF-8 w PHP gdzie nie ma nawet jak przeprowadzić konwersji z latin2 do utf8 a podpieranie się kulawym modułem iconv tylko ucina teksty w wypadku znaku który nie da się poddać konwersji. Ale co ja będę kopał leżącego… ;)

Nie mogłem się powstrzymać ;) i dodałem także swój komentarz do tego tekstu i w ogóle do kwestii rzekomej wyższości Rubiego nad Pythonem. Wiekszość osób które wpisały się do blogu Davida najwyraźniej ma mikre pojęcie o Pythonie. To prawda, że Ruby ma kilka cech lepszych od Pythona, ale prawdą jest także że Python posiada kilka cech lepszych od Rubiego. Postaram się później to jakoś podsumować w oddzielnym tekście.

Posted in ,  | Tagi ,  | 5 comments

Django 0.91

Opublikowane przez Jarosław Zabiełło Wed, 18 Jan 2006 18:19:00 GMT

Widzę, że developerzy Django wzięli sobie do serca to, aby w sposób profesjonalny rozwijać swój framework. Nie tylko zaprzestali udostępniać źródła wyłącznie w SVN, ale zadbali także aby dokumentacja poprzedniego wydania została zamrożona razem z nim. Dzięki temu osoby używające wersji 0.90 mają dokumentację do wersji 0.90. Zaś ci, co używają wersję 0.91 mają oddzielną dokumentację do wersji 0.91.

Więcej na temat zmian w wersji 0.91: tutaj.

Posted in ,  | Tagi  | brak comments

Ruby on Rails 1.0, Django 0.9

Opublikowane przez Jarosław Zabiełło Thu, 05 Jan 2006 10:36:00 GMT

Wyszła finalna wersja Ruby on Rails 1.0. Django jest zaś dostępne w wersji 0.9.

Posted in ,  | Tagi ,  | brak comments

Komentarze i filmy z konferencji Django + Ruby on Rails

Opublikowane przez Jarosław Zabiełło Thu, 05 Jan 2006 10:26:00 GMT

Zostały udostępnione nagrania wideo z ostatniej konferencji Snakes and Rubies organizowanej przez developerów Django oraz Ruby on Rails. Wiele osób umieściło także komentarze na temat tej konferencji w swoich blogach.

Posted in ,  | Tagi ,  | brak comments

Rails i Django organizują wspólną konferencję!

Opublikowane przez Jarosław Zabiełło Thu, 17 Nov 2005 20:00:00 GMT

3 grudnia developerzy Rubiego i Pythona mają się spotkać razem na uniwersytecie DePaul w Chicago. Będzie można usłyszeć dwóch liderów aplikacji webowych drugiej generacji. Przemawiać będzie twórca Railsów: David Heinemeier Hansson oraz twórca Django: Adrian Holovaty. Można wysłać za pomocą internetu pytania do obu mówców na które będą odpowiadać podczas konferencji. Zobacz http://snakesandrubies.com/event Mam nadzieję że będzie z tego dostępny jakiś film albo chociaż transkrypcja.

Posted in ,  | Tagi ,  | brak comments

Starsze wpisy: 1 2