Piramidalna zemsta Zope

Zagotowało się w świecie pythonowych frameworków webowych. Pylons, Repoze.BFG i być może TurboGears, nie mogąc sprostać konkurencji ze strony Django, postanowiły połączyć swoje siły.

Przesadziłem? Ok, z tym sprostaniem konkurencji ze strony Django to taka mała prowokacja. Niemniej jednak połączenie się wspomnianych frameworków jest oficjalnym faktem. Można o tym przeczytać na liście dyskusyjnej repoze.bfg, do czego zachęcam.

W kilku słowach ujmując zaistniałe zdarzenie, można powiedzieć, że repoze.bfg nie doczeka się wersji 1.4 (wersja 1.3 ukazała się 1 listopada… nomen omen w Święto Zmarłych), albowiem stało się właśnie frameworkiem Pyramid. Podobnie ma się sprawa z samymi Pylonsami, ktore niedawno doczekały się wersji 1.0 (linia 1.x będzie utrzymywana, według deweloperów, jeszcze przez parę lat), ale to co miało być Pylonsami 2.0 będzie po prostu frameworkiem Pyramid.

Pyramid rozwijany będzie w ramach projektu Pylons, który stanowić będzie zbiór różnych powiazanych technologii.

TurboGears, które bazuje na Pylonsach, jeszcze nie zdecydowało, czy również będzie się opierało na Pyramidzie, czy jednak zostanie na Pylons 1.0. Moim zdaniem zdecydują się na Pyramid.

Jakie są motywy powyższego kroku? Chodzi głównie o zwiększenie siły przebicia frameworku oraz o przezwyciężenie pewnych problemów, które Pylons miał ze swoją achitekturą:

(Jeden z twórców Pylons) discovered an architectural design flaw in Pylons [1]. The problem orients around the chosen strategy of implementing individual app
extensibility by allowing subclassing of the WSGIController

Sporo na ten temat można znaleźć w tej dyskusji. Obok długich tłumaczeń i wyjaśnień można tam też natrafić na dużą dozę niechęci i strachu ludzi przed Zope, z którego wywodzi się repoze.bfg. W dużej mierze wynika to jednak z braku wiedzy na temat tego czym jest Zope. Moim zdaniem komponenty wywodzące się z Zope, w tym architektura komponentowa (ang. Zope Component Architecture, ZCA) sprawią, że Pyramid będzie naprawdę elastycznym, dobrym frameworkiem. Warto mieć na niego oko.

Osobiście cieszę się, bo dobrze będzie mieć w Pythonie takie dwa frameworki jak Django i Pyramid. Cieszę się też, że używam Django, bo gdybym używał Pylonsów czy repoze.bfg to na dziś dzień miałbym przed sobą perspektywę migrowania aplikacji. Niby support ma być przez parę lat, ale zawsze to niefajnie pisać w czymś co ma już swojego lepszego następcę.

05. November 2010 by restless_being
Categories: Uncategorized | Tags: , , , | Leave a comment

Front-Trends, czyli konferencja o front-endach

Konferencja Front-Trends, odbyła się w październiku w Warszawie i chociaż nie miałem okazji w niej uczestniczyć, to jednak poświęcam krótki wpis temu ciekawemu wydarzeniu.

Osobiście w Warszawie, w dniach 21-22 października, nie byłem, ale byli inni, w tym Mekk, który napisał taką relację z konferencji, ze czuję się jakbym tam był. Szacunek i serdeczne podziękowania.

Konferencja dotyczyła front-endów, stąd sporo mówiono podczas niej o JavaScripcie (który wcale nie jest tylko front-endowy), HTML 5, CSS 3. Pojawiły się też tematy związane z rozwiązaniami dla urządzeń mobilnych.

Wszystkich zainteresowanych zachęcam do przeczytania szczegółowych relacji Mekka:

Ja czytałem to z wywieszonym jęzorem ;)

05. November 2010 by restless_being
Categories: Uncategorized | Tags: , , , | Leave a comment

Był sobie PyCon

W zeszłym tygodniu odbył się w Ustroniu trzeci polski PyCon. Byłem, widziałem, a oto moje wrażenia.

Rok temu na PyConie miałem zaszczyt wygłaszać prelekcję na temat Django oraz Pinaxa. Fajne doświadczenie, ale też wymagające sporej ilości czasu. Tego ostatniego w tym roku mi zabrakło, wobec czego pojechałem do Ustronia w charakterze zwykłego uczestnika.

Społeczność

Jak to ktoś ładnie napisał (Katharsis?) PyCon jest nieoficjalnym zlotem ludzi z kanału IRC #python.pl, a także #django-pl. Wyróżniamy się zwykle koszulkami z ładnymi nadrukami oraz przesiadywaniem w okolicach stołu bilardowego. Miło jest się ponownie spotkać lub zobaczyć po raz pierwszy (bo przecież kanały żyją i się rozrastają i ciągle pojawia się ktoś nowy) i oczywiście podyskutować na okołopythonowe tematy.

Zainteresowanych tym jak to wszystko naprawdę wyglądało odsyłam do blogów RMZ i Katharsisa, gdzie już są lub wkrótce pojawią się zdjęcia.

Oczywiście PyCon to też okazja do poznania ciekawych osób spoza IRC. W tym roku poznałem, o zgrozo, speców od Ruby On Rails z firmy Selleo. Nie znam RoR, ale mam do niego duży szacunek, tym ciekawiej było porozmawiać na temat różnic i podobieństw między tym frameworkiem a Django, a także ogólnie o Ruby i Pythonie oraz procesach wytwarzania oprogramowania. Tematów było zresztą więcej bo panowie imponowali rozległą wiedzą nie tylko techniczną ale i biznesową.

Technikalia

Z różnych względów nie byłem na wszystkich wykładach, ale spośród tych, które odwiedziłem najciekawsze były: warsztaty poprowadzone przez Marcina Bardzia na temat “Optymalizacji i profilingu metodami chałupniczymi” oraz prelekcja “Python: Fragmenty” Radomira Dopieralskiego.

Warsztaty pokazały w jaki sposób podejść do tematu badania wydajności kodu napisanego w Pythonie oraz jakie narzędzia można tu zastosować. Rzecz niewątpliwie przydatna w praktyce. Z kolei The Sheep, czyli Radomir, pokazywał “ciekawe” fragmenty kodu Pythona. Ciekawe czyli takie, które powodowały różne dziwne problemy, pomimo tego, że na pierwszy rzut oka wydawały się zupełnie w porządku. Bardzo pouczające, zachęcam do obejrzenia slajdów z tej prezentacji.

Bardzo fajna była też prezentacja Bartosza Krajnika na temat wykorzystania Pythona w laboratorium fizycznym. Nie jestem fizykiem, ale miło było zobaczyć jak dobrze sprawdza się Python w tym obszarze, tym bardziej, że wszystko było okraszone dużym entuzjazmem i poczuciem humoru prelegenta. Wykład ten bardzo dobrze uzupełnił wcześniejszą opowieść Mateusza Paprockiego o bibliotece SymPy podczas, której rosły serca wszystkim używającym Pythona matematykom.

Warto jeszcze wspomnieć lighting talka wygłoszonego przez reprezentanta MegiTeam, rozpoczętego słowami: “Jeśli serwujecie swoje serwisy WWW używając Apache to robicie źle”. W ciekawy i nieco kontrowersyjny sposób mówca zachęcał do używania nginxa, przedstawiając liczne argumenty na poparcie swojej tezy. W skrócie nginx jest szybszy, stabilniejszy (“napisany w starym dobrym radzieckim stylu” i nigdy się nie wysypał) oraz bezpieczniejszy (odporny na DDOSy) niż Apache. No to się zainteresowałem cherokee

Brakowało niestety jakichś talków na tematy związane z web developmentem. Jedynym wyjątkiem była krótka prezentacja o Plone 4, nieźle zrobiona, ale w przyszłym roku chciałbym zostać przekonany do tego, że warto używać Plone. Na dziś dzień wiem, że Plone się rozwija, ale chciałbym się dowiedzieć się jak z tym pracować na codzień, a przede wszystkim jak wygląda obecnie sprawa pisania własnych rozszerzeń. Niestety Zope, na którym Plone bazuje, a którego swego czasu używałem, zawsze miał słabą dokumentację. Znacznie bogatsza dokumentacja samego Plone też nie była rewelacyjna – były to raczej krótkie how-to, które doś szybko się dezaktualizowały. Niestety, ale doskonała dokumentacja Django rozpieszcza.

Podsumowanie

Ogólnie było naprawdę fajnie i jestem zadowolony, że tam byłem. Cieszy duża ilość osób, w tym sporej grupy dziewczyn. Niedociągnięć i słabszych talków też by się kilka znalazło, ale właściwie narzekać mogę tylko na brak prelekcji o web developmencie, który mnie najbardziej interesuje. Rok temu był buildout Dominika Szopy i legendarny już talk o obsysaniu Jarka Zgody, tym razem praktycznie nic. Nawiasem mówiąc to odniosłem wrażenie, że mało kto pamięta prawdziwy sens tej ostatniej prezentacji. Zachecam do przyjrzenia się slajdom i wyczytania między wierszami co tak naprawdę obsysało. To tyle. Do zobaczenia za rok.

14. October 2010 by restless_being
Categories: Uncategorized | Tags: , | Leave a comment

Templates in a django project

A smart way of placing templates in your django project.

So you’re starting a new project in Django? One thing you’ll obviously want are templates and you’ll have to decide where to put them.

The Default Way

The method I used for a long time is the method described in Django Tutorial and used for example in Pinax. It is based on templates folder(s) which is placed somewhere in your filesystem, most often directly in your project’s root.

- project
    -apps
        -app1
        -app2
    -templates
        -app1 (templates for app1)
        -app2 (templates for app2)
    -other folders/files

To get it working some configuration in settings.py is also required:

# Configure Django to first load templates from filesystem
# and then from application directories
# These are default settings
TEMPLATE_LOADERS = [
    "django.template.loaders.filesystem.Loader",
    "django.template.loaders.app_directories.Loader",
 ]

# Define where exactly Django should look for templates
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
TEMPLATE_DIRS = [
    os.path.join(PROJECT_ROOT, "templates"),
]

You can read more about settings used above here.

With this simple config you can create a theme for your project. Just start creating templates in templates directory. It is important to remember that it is prefferable to place templates in subdirectories to keep templates for specific apps separated.

However there are inconveniences with this configuration:

  • First is about templatetags – if you need a tag to render something project specific where should you place it’s code? You need to create a dedicated application for this case.
  • Second is about i18n – to generate locales only for templates in Django < 1.2 it was required to manually move apps folders out of project directory, then call bin/django makessages -l pl (or whatever lang you use) and after that move apps back to project directory. Why? Because makemessages browses all folders under current folder so it would generate locales also for applications from apps. The good news is that Django 1.2 has provided --ignore option to makemessages that allows exclusion of some directories while generating messagefiles.

The LFC Way

The method I use now is based on a LFC‘s way of doing things. It is very simple and doesn’t have inconveniences of previous method.

The main concept here is an application. Your theme is just an ordinary application, so instead of defining TEMPLATE_DIRS it is enough to add yourproject_theme app to INSTALLED_APPS.

Django searches for templates in apps specified in INSTALLED_APPS browsing them in order of definition so it is important to place yourproject_theme application before any other applications. For example:

INSTALLED_APPS = (
    "lfc_theme",
    "django.contrib.admin",
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    "django.contrib.flatpages",
    "django.contrib.sitemaps",
    "django.contrib.comments",
    "django_extensions",
    "lfc",
    "lfc_blog",
    "portlets",
    "tagging",
    "contact_form",
    "pagination",
    "workflows",
    "permissions",
    "gunicorn",
)

Main advantages of having a theme as an application are that you can have locales, templatetags and even static files as well as project specific utility functions in one place – your theme application.

Curious about example? Look into LFC Theme.

Summary

Both methods are simple to use but the second has advantages and IMHO results in a cleaner structure of a project.

30. June 2010 by restless_being
Categories: Uncategorized | Tags: , , | Leave a comment

Django-LFC

New shining star in the world of Django: Lighting Fast CMS – sneak preview

Django and CMS projects

Some time ago I wrote about Django powered CMS projects. In particular I described django-cms and also mentioned Fein CMS. Both projects are really good ones (compare them) but… their competitor has just arrived (ok, almost because it is still in alpha) – Lighting Fast CMS.

LFC comes from the author of Lighting Fast Shop and shares some elements with that project so if you used LFS you will be positively surprised.

A bite of django-lfc

My first impression was: “oh.. it’s plonish!”. Yup, LFC resembles Plone to me – I really like this kind of clean interface and available options. It’s not Django’s Admin any more (see django-cms and feincms) but LFC’s own management panel.

Lighting Fast CMS - management panel

LFC is intuitive. I was able to set up a simple site without reading any docs. Of course there are docs! It is important thing in any serious project and LFC is going to be serious.

Full list of LFC features is rather long, so if you are interested just follow the link. I especially like: content types, portlets,

Lighting Fast CMS - portlets

authorisation based on mapping between roles and permissions

Lighting Fast CMS - permissions

and… workflows.

Lighting Fast CMS - workflows

There is no rose without a thorn

Sadly, LFC is not yet 1.0 final, so nobody can expect it to be bug free and in fact there is some bugs. For example it is quite easy to set up running instance of LFC using buildout, but it quickly turns out that it is limited to work on supplied sqlite database only. There are still some problems that make it hard to run LFC on other database engines like postgres. However, everything is possible so if you’re interested in how to set up current (1.0 alpha 8 – “Man o’ War”) release of LFC to work with postgres please read on.

LFC and Postgres

You can read about LFC installation in the official docs. The important part is to call:

hg clone http://bitbucket.org/diefenbach/lfc-buildout-development

to get a local copy of LFC.However, in my case, before I performed the next step in installation process I had to modify buildout.cfg. Here is mine:

[buildout]
parts =
    PIL
    django
    lfc
    lfc_theme
    lfc_blog
    tagging
    contact-form
    django-fcgi
    permissions
    portlets
    workflows

[lfc]
recipe = mercurialrecipe
repository = http://bitbucket.org/diefenbach/django-lfc/

[lfc_theme]
recipe = mercurialrecipe
repository = http://bitbucket.org/diefenbach/lfc-theme

[lfc_blog]
recipe = mercurialrecipe
repository = http://bitbucket.org/diefenbach/lfc-blog

[permissions]
recipe = mercurialrecipe
repository = http://bitbucket.org/diefenbach/django-permissions

[portlets]
recipe = mercurialrecipe
repository = http://bitbucket.org/diefenbach/django-portlets

[workflows]
recipe = mercurialrecipe
repository = http://bitbucket.org/diefenbach/django-workflows

[tagging]
recipe = mercurialrecipe
repository = http://bitbucket.org/fivethreeo/django-tagging-inheritance/

[PIL]
recipe = zc.recipe.egg:custom
egg = PIL==1.1.6
find-links = http://dist.repoze.org/

[contact-form]
recipe = gocept.download
url = http://bitbucket.org/ubernostrum/django-contact-form/get/1d3791fa4dfb.zip
md5sum = 8e3e257fda807fef5f3abcc6b5beb398

[django-fcgi]
recipe = collective.recipe.template
port  = 8000
input = ${buildout:directory}/misc/conf/django-fcgi.sh.in
output = ${buildout:directory}/bin/django-fcgi.sh

[django]
recipe = djangorecipe
version = http://code.djangoproject.com/svn/django/branches/releases/1.1.X
eggs =
    PIL==1.1.6
    psycopg2
    feedparser
    pysqlite
    django-pagination
    django-extensions

project = lfc_project
settings=settings
extra-paths =
    ${buildout:directory}/lfc_project
    ${buildout:directory}/parts/permissions
    ${buildout:directory}/parts/workflows
    ${tagging:location}
    ${contact-form:location}
    ${lfc:location}
    ${lfc_theme:location}
    ${lfc_blog:location}
    ${permissions:location}
    ${workflows:location}
    ${portlets:location}

urls = lfc_project/urls

My modifications included:

  • setting a specific version of PIL (PIL == 1.1.6) – otherwise there was an import error
  • setting a specific version of Django – to include some patches for bugs that were causing LFC to raise exceptions when used with postgres

After everything was installed I changed settings.py to configure postgres database there.

My next step was to comment out last line: post_syncdb.connect(register) in parts/lfc/models.py. This line makes register function to be called on syncdb signal, but there is a problem because register is called multiple times. This breaks something when register function is trying to add the same objects for the second time (there is an unique index) raising database transaction errors.

After commenting the line out I ran syncdb and successfully created database tables and my superuser. Then I uncommented the line and called syncdb again. This raised an error but in general it worked registering important things like portlets, templates and content types.

Updated content: The last thing to do is to load some data. There is a helpful script initialize_lfc.py in scripts directory, so it is enough to start Django’s shell (bin/django shell) and run:

from scripts import initialize_lfc
initialize_lfc.run()

The last thing I had to do was to add a Portal instance. To accomplish this I disabled lfc.context_processors.main context processor and added django.contrib.admin to INSTALLED_APPS in settings.py. I also added (r'^admin/(.*)', admin.site.root), to urls.py. Then I was able to enter admin panel and add Portal object there. After adding Portal I enabled (uncommented) lfc.context_processors.main and was able to work with LFC management panel.

After doing the above I was able to add things through admin panel. For example I got an exception when I tried to enter “Roles” menu. I had to add a role in admin to overcome this.

Another thing I did was to call bin/django loaddata to load predefined fixtures from LFS apps (you can find it in parts directory). I’m not sure why but these fixutres are not loaded automatically.

Summary

LFC has some cool features, not so bad docs and good hmm… feeling. I just like it, it’s nice, pretty, it has good clean website containing even screencasts (to be honest I don’t like screencasts so I didn’t watch them :D ). I’m going to use LFC in my project soon. It’s not yet 1.0 but it already has some live sites. I’m sure it will be a serious competitor to django-cms and feincms, so don’t bother to give it a try.

07. May 2010 by restless_being
Categories: Uncategorized | Tags: , , | Leave a comment

Django i formularze

Formularze są jednym z ważniejszych atutów Django. W tym krótkim wpisie wskazuję dwa artykuły przedstawiające różne ciekawe sposoby pracy z formularzami oraz pewną interesującą aplikację.

Zbiegi okoliczności jak najbardziej istnieją. Nie dalej jak wczoraj wgryzałem się w różne ciekawe triki dotyczące wykorzystania formularzy, a w dniu dzisiejszym niejaki Shabda opublikował artykuł na ten właśnie temat. Artykuł na tyle dobry, że skłonił mnie do wrzucenia tu informacji o nim oraz o jeszcze kilku ciekawostkach związanych z formularzami. Zapraszam do zapoznania się z poniższymi materiałami:

14. January 2010 by restless_being
Categories: Uncategorized | Tags: | Leave a comment

O Buildoucie i Django

Buildout to stworzony w języku Python system służący do zautomatyzowanego budowania oprogramowania. Oprogramowania zwykle złożonego z wielu różnych części, niekoniecznie opartych na Pythonie.

Buildout?

Z Buildoutem zetknąłem się po raz pierwszy wiele lat temu, gdy jeszcze bliżej było mi do Zope niż do Django. Zetknąłem się nie znaczy, że go używałem, ale jak mówi staropolskie powiedzenie “co się odwlecze to nie uciecze” i wygląda na to, że czas Buildouta nastał właśnie teraz. Owo teraz zaczęło się od Dominika “Dominno” Szopy i jego prezentacji na temat Buildouta, którą wygłosił na konferencji PyConPL. Temat na tyle mnie zainteresował, że postanowiłem zapoznać się z buildoutem bliżej i… jestem pozytywnie zaskoczony. W tym wpisie podzielę się kilkoma spostrzeżeniami na temat wykorzystania Buildouta we własnym projekcie Django.

Wprowadzenie do Buildouta

Najciekawsze wprowadzenie do Buildouta w języku polskim to artykuł wspomnianego Dominika Szopy z PyConPL. Niestety nie jest on chyba dostępny w Sieci (a przynajmniej nie potrafię go znaleźć), pozostaje więc zapoznanie się z samą tylko prezentacją Dominika oraz anglojęzycznymi materiałami. Poniżej kilka słów wprowadzenia w temat ode mnie, a potem linki do wybranych tutoriali.

Buildout z bliska

Buildout pozwala na zautomatyzowane instalowanie aplikacji wraz ze wszystkimi zależnościami. Jak można się spodziewać, aby taka zautomatyzowana instalacja zadziałała po pierwsze potrzebny jest Buildout, a po drugie plik konfiguracyjny, w którym znajdą się przepisy wskazujące co ma być zainstalowane. W praktyce oznacza to, że potrzebne są dwa pliki: bootstrap.py oraz buildout.cfg.

Żeby zainstalować Buildouta wystarczy pobrać i uruchomić skrypt bootstrap.py.

[ext@sandarcher buildout]$
    wget http://svn.zope.org/*checkout*/zc.buildout/trunk/bootstrap/bootstrap.py
    (...)
    2009-12-25 23:17:02 (228 KB/s) - zapisano `bootstrap.py' [3807]
[ext@sandarcher buildout]$ touch buildout.cfg
[ext@sandarcher buildout]$ ls
    bootstrap.py buildout.cfg
[ext@sandarcher buildout]$ python bootstrap.py
    Creating directory '/home/ext/tmp/buildout/bin'.
    Creating directory '/home/ext/tmp/buildout/parts'.
    Creating directory '/home/ext/tmp/buildout/eggs'.
    Creating directory '/home/ext/tmp/buildout/develop-eggs'.
    Generated script '/home/ext/tmp/buildout/bin/buildout'.

Następnie należy wywołać polecenie bin/buildout, co spowoduje, że Buildout zainstaluje to co zostało zdefiniowane w pliku konfiguracyjnym buildout.cfg.

W skrótcie to tyle, ale warto jeszcze wspomnieć o tym co znajduje się w pliku konfiguracyjnym. Otóż Buildout oparty jest na recipes czyli przepisach. Każdy przepis powoduje wykonanie różnych czynności, takich jak na przykład: zainstalowanie Django, stworzenie skrótu na dysku, czy zainstalowanie pakietu przez configure, make, make install. Tworząc plik konfiguracyjny wpisuje się w nim konkretne przepisy i podaje im parametry.

Więcej szczegółowych informacji o Buildoucie znaleźć można wśród poniższych materiałów:

Struktura plików i katalogów

Tutoriale tutorialami, ale tym co mnie najbardziej interesowało było to jak “zbuildoutować” mój istniejący, lub właśnie tworzony projekt w Django. Jakie stworzyć katalogi, gdzie umieścić konfig Buildouta, itp itd. Z powyższych materiałów niestety nie wynika to wprost dlatego przedstawię tu mój sposób. Jeśli ktoś zna lepszy lub inny to zapraszam do komentowania.

Jak już wspomniałem Buildout wymaga w zasadzie dwóch plików: konfiguracyjnego buildout.cfg oraz inicjalizującego środowisko bootstrap.py. Ja do tego dokładam jeszcze projekt djangowy i w efekcie moja struktura plików i katalogów wygląda następująco:

- bootstrap.py
- buildout.cfg
- project/ (katalog z moim projektem)

To, że mój projekt nazywa się “project” jest zapisane w konfiguracji dla Buildouta – będzie to widoczne w przedstawionym nieco dalej fragmencie buildout.cfg w sekcji [django].

Powyższe umieszczam w repozytorium, po czym wykonuję np. na innym serwerze checkout (pobranie z repozytorium), odpalam bootstrap.py (instalacja Buildouta) i wywołuję bin/buildout (instalacja projektu i zależności). W efekcie uzyskuję w pełni skonfigurowane środowisko do uruchamiania projektu.

Odrobina customizacji

Wśród wielu przydatnych opcji Buildouta warto wspomnieć o rozszerzaniu plików konfiguracyjnych. Rozszerzanie pozwala na zdefiniowanie różnych plików konfiguracyjnych np. dla środowiska deweloperskiego czy testowego, które bazując na innym pliku konfiguracyjnym modyfikują niektóre spośród zawartych w nim ustawień.

Fragment przykładowego pliku buildout.cfg:

[buildout]
parts = PIL django omlette cms-media

[PIL]
recipe = zc.recipe.egg
eggs = PIL==1.1.6
find-links = http://dist.repoze.org

[django]
recipe = djangorecipe
version = 1.1
project = project
eggs =
     PIL == 1.1.6
     psycopg2
     egenix-mx-base
     south
     django-reversion
     django-tinymce
     django-cms
wsgi = true
settings = production
extra-paths = ${buildout:directory}/project/apps
(...)

Powyższa konfiguracja instaluje PIL oraz kilka bibliotek i aplikacji określonych w sekcji eggs. Warto tu także zwrócić uwagę na ciekawe ustawienia w przepisie dla Django, takie jak “wsgi=True”, które określa czy ma być generowany skrypt .wsgi pozwalający na uruchamianie projektu spod mod_wsgi oraz “settings=production” wskazujące jaki plik jest plikiem konfiguracyjnym projektu. Wpis “extra-paths” pozwala na określenie ścieżek, które zostaną dodane do PYTHONPATH, w tym przypadku jest to folder “apps” w moim projekcie, w którym to folderze trzymam wykonane na potrzeby projektu aplikacje.

Przykładowy plik devel.cfg dla środowiska deweloperskiego:

[buildout]
extends = buildout.cfg

[django]
wsgi=false
settings=development

Plik devel.cfg rozszerza konfigurację zawartą w buildout.cfg poprzez modyfikację ustawień dla sekcji [django]. Sekcja ta to przepis instalujący Django, który zostaje tu ustawiony tak, aby w środowisku deweloperskim nie generował pliku .wsgi oraz aby używał pliku o nazwie development.py jako konfiguracji Django.

Jak korzystać z takich rozszerzających plików konfiguracyjnych? Bardzo prosto:

bin/buildout -c devel.cfg

Uwaga na PIL

PIL czyli Python Imaging Library jest bardzo często wykorzystywany przez różne aplikacje Django (mam tu na myśli głównie aplikacje do wielokrotnego wykorzystania (ang. reusable apps)). Niestety biblioteka ta od zawsze sprawiała kłopoty przy instalacji i tak samo było podczas moich eksperymentów z PILem i Buildoutem. Żaden ze sposobów instalacji PIL podany w podlinkowanych wyżej materiałach nie chciał zadziałać. PIL instalował się w złej wersji, albo w dwóch różnych wersjach i Django nie chciało go “zobaczyć”. Przyczyną problemu okazało się to, że wydana została nowa wersja PIL, a rozwiązanie polegało na określeniu w pliku konfiguracyjnym w dwóch miejscach dokładnej wersji PIL, co widać w przykładzie poniżej.

[PIL]
recipe = zc.recipe.egg
eggs = PIL==1.1.6
find-links = http://dist.repoze.org

[django]
recipe = djangorecipe
version = 1.1
project = project
eggs =
     PIL == 1.1.6

Jeśli więc po przeczytaniu tutoriala do Buildouta występują problemy z instalacją PIL sugeruję wypróbować powyższą konfigurację.

Dlaczego buildout a nie PIP?

PIP czyli Pip Installs Packages to narzędzie zastępujące easy_install. Tym co czyni PIP podobnym do Buildouta są pliki wymagań (ang. requirements), które pozwalają na zdefiniowanie zestawu pakietów do zainstalowania. Taki plik wymagań ma zwykle bardzo prostą postać np.:

MyApp
Framework==0.9.4
Library&gt;=0.2
-e svn+http://myrepo/svn/MyApp#egg=MyApp

Pierwsze trzy wpisy określają konkretne biblioteki do zainstalowania (np. z PyPi), ostatnia linia wskazuje, że zainstalowana ma być aplikacja z repozytorium svn. Jeśli plik wymagań nazywa się requirements.txt to możemy zainstalować zdefiniowane w nim pakiety wydając polecenie:

pip install -r requirements.txt

Co bardzo istotne, zadaniem PIPa jest instalowanie pakietów Pythona, które są stworzone zgodnie ze standarowymi sposobami dystrybucji (zdefiniowanymi w distutils). Oznacza to, że każdy instalowany pakiet musi być pakietem pythonowym oraz musi posiadać prawidłowy plik setup.py.

Chociaż PIP i jego pliki wymagań sprawdzają się w wielu projektach (wiem bo sam korzystam) to jednak PIP ma pewne istotne ograniczenia i tak naprawdę jest narzędziem przeznaczonym do czegoś innego niż Buildout, który ma po prostu znacznie większe możliwości. Najlepszym dowodem na to jest fakt, że istnieje dla Buildouta przepis pozwalający na instalacje pakietów za pomocą PIP.

Dlaczego virtualenv i Buildout?

Na koniec kilka słów na temat virtualenv i Buildouta. Virtualenv to narzędzie do tworzenia wirtualnych wyizolowanych środowisk Pythona. W praktyce Buildout instalując aplikacje i różne pakiety działa nieco podobnie do virtualenva, gdyż umieszcza je w swoich własnych katalogach (wygenerowanych przez bootstrap.py) i nie narusza systemowego Pythona.

Kiedy więc warto połączyć virtualenv z Buildoutem? Otóż wtedy, gdy chcemy aby tworzone środowisko nie korzystało w ogóle z bibliotek z systemowego Pythona. Wówczas należy wygenerować nowe wirtualne środowisko za uruchamiając polecenie virtualenv z parametrem –no-site-packages i dopiero w nim uruchomić Buildouta.

Podsumowanie

Buildout jest narzędziem, którym zdecydowanie warto się zainteresować, po to aby… ułatwić sobie życie. Buildout przydaje się zarówno przy umieszczaniu projektu w wielu różnych środowiskach (deweloperskim, testowym, produkcyjnym) jak i przy pracy grupowej, gdy trzeba zainstalować projekt u kilku deweloperów. Ze swojej strony zdecydowanie zachęcem do wypróbowania Buildouta we własnych projektach.

27. December 2009 by restless_being
Categories: Uncategorized | Tags: , | Leave a comment

Django i CMSy

Niedawno, zasiadając do realizacji pewnego zadania, stwierdziłem, że potrzebuję użyć jakiegoś CMSa. Niewątpliwie najlepszym systemem tego typu napisanym w Pythonie jest Plone, tyle, że okazał się on być zbyt duży w stosunku do moich potrzeb – szukałem czegoś małego, lekkiego i najchętniej w Django.

Plone

Plone posiada przyjazny interfejs użytkownika i całą masę pluginów, co pozwala na “wyklikanie” nawet dość złożonych rozwiązań. Przy tym jednak oparty jest na Zope, co oprócz wielu zalet związanych z możliwościami samego Zope powoduje, że po pierwsze potrzebny jest ponadstandardowy hosting, a po drugie, w przypadku, gdy zachodzi potrzeba dopisania własnego rozszerzenia trzeba pokonać dość stromą ścieżkę nauki Zope. Szczęśliwie Plone, w odróżnieniu od samego Zope, ma przyzwoitą dokumentację obejmującą także programowanie, ale pomimo tego łatwo nie jest. Podsumowując, dla większych CMS-ów Plone jest rozwiązaniem godnym rozważenia, dla mniejszych niekoniecznie.

CMSy w Django

Jak już powiedziałem, potrzebowałem mniejszego CMSa, najlepiej opartego na moim ulubionym Django. Z pomocą przyszła mi strona z porównaniem djangowych CMSów, dzięki której zdecydowalem się na użycie django CMS 2.0. Najciekawszą alternatywą dla niego był Fein CMS, ale odpadł on z uwagi na to, że jest nieco zbyt magiczny (przynajmniej na pierwszy rzut oka).

Dodam, że istnieje jeszcze jeden ciekawy CMS, nie ujęty we wspomnianym porównaniu. CMS, który wydaje się mieć bardzo duże możliwości, ale niestety praktycznie nie ma dokumentacji. Jest to Ella, stworzona przez naszych sąsiadów zza południowej granicy. Mam nadzieję, że dokumentacja się wkrótce pojawi, zresztą rozmawiałem o tym na Pyconie z jednym z twórców Elli Honzą Kralem i obiecał, że postarają się coś w tym temacie zrobić. Zobaczymy.

django CMS

django CMS ujmuje ładną i przejrzystą stroną domową z dużą ilością dokumentacji. Po prostu od razu chce się go używać. Poniżej przedstawiam proces instalacji django CMS oraz informacje o tym jak wygląda praca z tym narzędziem.

Instalacja

  1. Najpierw należy pobrać źródła django CMS ze strony projektu (lub źródła z githuba). Potem trzeba zainstalować django CMS korzystając na przykład z polecenia
    python setup.py install

    Najlepiej zrobić to w ramach virtualenva, aby nie śmiecić w systemowym Pythonie.U mnie wygląda to następująco (używam virtualenvwrappera):

    e-X:~$ mkvirtualenv djangocms
    (djangocms)e-X:~$ easy_install django
    (djangocms)e-X:~$ easy_install south
    (djangocms)e-X:~$ easy_install django-reversion
    (djangocms)e-X:~$ cd
    (djangocms)e-X:~/$ python setup.py install
  2. W kolejnym etapie należy utworzyć projekt, który będzie bazował na django CMS. Można tu albo utworzyć nowy projekt poleceniem:
    django-admin startproject mycms i skonfigurować go zgodnie z instrukcją, albo użyć przykładowego projektu dołączonego do django CMS. Na potrzeby tego wpisu wykorzystałem tę drugą opcję, czyli skorzystałem z projektu przykładowego “example”.

    (djangocms)e-X:~$ cdvirtualenv
    (djangocms)e-X:~/virtualenvs/djangocms$ mkdir src
    (djangocms)e-X:~/virtualenvs/djangocms$ cd src
    (djangocms)e-X:~/virtualenvs/djangocms/src$cp /example example
  3. Następnie należy utworzyć bazę danych. Ponieważ korzystam z Postgresa, konfigurację bazy zdefiniowałem następująco (w settings.py):
    DATABASE_ENGINE = 'postgresql_psycopg2'
    DATABASE_NAME = 'examplecms'
    DATABASE_USER = 'cms'
    DATABASE_PASSWORD = 'xxx'

    po czym utworzyłem odpowiednią bazę danych w Postgresie i wygenerowałem w niej struktury danych. To ostatnie wykonałem korzystając z syncdb oraz dostarczonych z django CMS migracji obsługiwanych przez South.

    (djangocms)e-X:~/virtualenvs/djangocms/src/example$ ./manage.py syncdb
    (djangocms)e-X:~/virtualenvs/djangocms/src/example$ ./manage.py migrate
  4. Aby CMS mógł działać trzeba poprawnie skonfigurować media, czyli grafikę i javascript. W tym celu wystarczy zrobić link symboliczny do mediów w folderze projektu. U mnie wygląda to tak:
    (djangocms)e-X:~/virtualenvs/djangocms/src/example$
    ln -s ../../lib/python2.6/site-packages/django_cms-2.0.0.alpha-py2.6.egg/cms/media/
                                                                      cms_media

    i w settings.py

    MEDIA_ROOT = os.path.join(PROJECT_DIR, 'cms_media')
  5. Pozostało już tylko uruchomić uruchomić CMSa.Najpierw serwer
    (djangocms)e-X:~/virtualenvs/djangocms/src/example$ ./manage.py runserver

    a potem potem stronę w przeglądarce:

    http://localhost:8000

    Jeśli wszystko jest ok, to powinna się pojawić strona powitalna z widocznym logo django CMS.

Tworzenie stron

Kiedy CMS jest już zainstalowany, skonfigurowany i uruchomiony trzeba wprowadzić do niego trochę contentu. W django CMS zasadniczym contentem są strony (Page) oraz umieszczane w nich pluginy.

Aby stworzyć nową stronę należy przejść do panelu administracyjnego: http://localhost:8000/admin i dodać nową stronę (Page) w sekcji CMS. Po podaniu tytułu strony, wybraniu języka i szablonu warto kliknąć “save and continue editing” po to by określić szczegółowe parametry strony.

Django CMS - nowa strona

Języki jakie ma obsługiwać CMS, dostępne szablony stron, a także wiele innych parametrów CMS konfiguruje się w settings.py. Pełna lista opcji konfiguracyjnych django CMS znajduje się oczywiście w dokumentacji.

  1. Szablony
    Szablon przypisywany do strony określa jej layout. Na przykład mogę stworzyć szablon 1kolumna.html, który będzie używany dla stron z jedną kolumną oraz szablon 2kolumny.html dla stron z dwoma kolumnami itd. Oprócz layoutu w szablonach umieszcza się placeholdery, czyli tagi w formie {% placeholder "right_column %}, {% placeholder "body" %}. Te tagi wskazują miejsca, w które wstawiane będą pluginy. Fragment template z przykładowej aplikacji wygląda następująco:

    <h2>Content</h2>
    {% block content %}
        <div style="width:70%">
            <h3>title placeholder {% page_attribute title %}</h3>
            <div style="float:right;width:25%">
                <h3>Right column placeholder</h3>
                {% placeholder right-column %}
            </div>
            <div>
                <h3>body placeholder</h3>
                {% placeholder "body" %}
            </div>
        </div>
    {% endblock %}

  2. Publikowanie stron
    Strona po utworzeniu nie jest od razu widoczna dla użytkowników. Autor może spokojnie nad stroną popracować, a dopiero potem ją opublikować zaznaczając znacznik Is published. Jeśli dodatkowo strona ma być widoczna w menu nawigacyjnym trzeba zaznaczyć także opcję In navigation.

  3. Pluginy
    Na powyższej ilustracji można zauważyć sekcje Right column oraz Body. Jest to nic innego niż wspomniane wcześniej placeholdery, w których można zamieszczać pluginy. W widocznym na obrazku placeholderze Right column został umieszczony plugin typu Text. Inne dostępne pluginy to między innymi: link, obrazek, mapa google, kontrolka flash.

  4. Uprawnienia
    Dla każdej strony możemy zdefiniować uprawnienia, które określają co dany użytkownik lub grupa użytkowników może ze stroną robić (edytować, usuwać, moderować itp.). Co bardzo przydatne uprawnienia mogą się automatycznie propagować na strony umieszczone niżej w hierarchii. Dla każdej ze stron można także określić, czy dostęp do niej wymaga logowania oraz czy ma się ona pokazywać w menu wszystkim, czy tylko zalogowanym użytkownikom.

Korzystając z przedstawionych opcji można, na bazie własnych szablonów, budować dość złożone strony, w ramach których określa się kto i co może zrobić, jakich pluginów użyć itd. Nadmienię jeszcze, że interfejs django CMS bazuje w dużej mierze na Ajaxie, dzięki czemu hierarchie stron buduje się za pomocą wygodnego mechanizmu przeciągnij-i-upuść.

Własne rozszerzenia

Własne rozszerzenia w django CMS można tworzyć na kilka sposobów. Pierwszy to napisanie własnego pluginu, który będziemy umieszczać w różnych placeholderach. W skrócie plugin to klasa dziedzicząca po CMSPluginBase i posiadająca funkcję render, która odpowiada za wyświetlenie pluginu.

  1. Pluginy
    Przykładowy plugin, który wyświetla formularz wyszukiwania:

    from cms.plugin_base import CMSPluginBase
    from cms.plugin_pool import plugin_pool
    from django.utils.translation import ugettext as _
    from cms.models import CMSPlugin
    from search_engine.forms import DJCMSSearchForm
    
    class CMSSearchPlugin(CMSPluginBase):
        model = CMSPlugin
        name = _("CMS search")
        render_template = "search_engine/cms_search.html"
    
        def render(self, context, instance, placeholder):
            request=context['request']
            if request.GET.get('q', None):
                form = DJCMSSearchForm(request, request.GET)
            else:
                form = DJCMSSearchForm(request, initial={'q':_('enter search query')},)
            context.update({'placeholder':placeholder,
                                    'request':context['request'],
                                    'search_form':form})
            return context
    
    plugin_pool.register_plugin(CMSSearchPlugin)

    oraz jego template:

    <div id="search-panel">
        <p>SZUKAJ</p>
        <form method="get" action="{% page_id_url "search" %}">
        <p>
            {{ search_form.q }}
            <input type="submit" value="szukaj" />
        </p>
        </form>
    </div>

    Tworzenie pluginów jest dość dobrze opisane w dokumentacji, w sekcji custom plugins, więc tam odsyłam po szczegóły.

  2. Własne aplikacje
    Własna aplikacja może zostać wpięta do django CMS w bardzo prosty sposób. Wystarczy zdefiniować w settings.py, że dana aplikacja ma być dla django CMS dostępna:

    CMS_APPLICATIONS_URLS = (
        ('someapp.urls', 'Some application'),
        ('sampleapp.urls_en', 'Sample application English URLs'),
        ('sampleapp.urls_de', 'Sample application German URLs'),
    )

    Potem należy utworzyć nową stronę (lub użyć istniejącej) i w opcjach zaawansowanych wskazać aplikację, z której ta strona skorzysta. Przedstawia to poniższa ilustracja.
    Django CMS - własna aplikacjaJeśli strona, do której została przypięta aplikacja np. obsługująca aktualności nazywa się newsy to każdy url po newsy będzie obsługiwany przez tę aplikację. Co więcej w ramach szablonów aplikacji podpinanych w ten sposób do stron można korzystać z możliwości CMSa (np. placeholderów), dzięki czemu pluginy zdefiniowane na stronach do których podpięto aplikację będą nadal działać. Mechanizm podłączania własnych aplikacji jest prosty i efektywny i bardzo przydał mi się przy realizacji mojego projektu.

Podsumowanie

Po raz kolejny potwierdziła się zasada mówiąca, aby przed rozpoczęciem pisania sprawdzić czy nie ma już gotowego rozwiązania. Django może się pochwalić kilkoma ciekawymi CMSami, wśród których pozytywnie wyróżnia się django CMS posiadający ładną stronę domową, dobrą dokumentację, a przede wszystkim sprawdzający się w rzeczywistym działaniu. Przy wszystkich swoich zaletach jest to jednak zdecydowanie inna klasa rozwiązania niż wspomniany na początku Plone, ale to akurat było dla mnie zaletą – django CMS był właściwym narzędziem do zrealizowania stojącego przede mną zadania.

21. October 2009 by restless_being
Categories: Uncategorized | Tags: , , | Leave a comment

Strona WWW w IE6

Przy okazji opracowywania nowej wersji layoutu dla pewnego systemu przyszło mi rozprawić się z kilkoma bugami w przeglądarce Internet Explorer 6. W tym wpisie wskażę kilka ciekawych rozwiązań, o których warto pamiętać mierząc się z IE6.

Internet Explorer 6 znany jest z tego, że sprawia twórcom stron liczne problemy. Wynika to z faktu, że przeglądarka ta w wielu miejscach nie jest zgodna ze standardami World Wide Web Consortium (W3C).

Jak sobie radzić z IE6

Poniżej zamieszczam kilka ciekawych rozwiązań, o których warto pamiętać podczas tworzenia strony WWW:

  • Zachęcanie użytkowników do migracji – IE6 jest po prostu przestarzały dlatego warto zachęcać jego użytkowników do przejścia na IE7 lub IE8, lub na inne przeglądarki takie jak Firefox czy Chrome. Deweloperom stron przychodzą tu z pomocą serwisy typu No more IE6 czy IE6 Update, oferujące fragmenty kodu do wklejenia na stronie WWW. Użytkownicy IE6, którzy odwiedzą stronę wykorzystującą taki kod zobaczą informację w stylu “Twoja przeglądarka jest przestarzała, zaktualizuj ją”. Niestety tekst będzie po angielsku, ale twórcy ie6nomore obiecują, że niedługo udostępnią skrypt z polską wesją językową).
  • Naprawianie IE6 – IE6 można naprawić wykorzystując rozmaite skrypty takie jak IE7-js. Zastosowanie takiego skryptu na stronie sprawia, że IE6 staje się zgodny z IE7 lub IE8 – w zależności od wybranej wersji. W praktyce nie jest tak różowo, bo nie wszystkie problemy są usuwane, ale mogę stwierdzić, że jest zauważalnie lepiej.
  • Wykorzystanie frameworków CSS – frameworki CSS pozwalają na budowanie interfejsów, które będą poprawnie wyświetlane w różnych przeglądarkach. Ze swojej strony polecam 960.gs – bardzo prosty i przyjemny z użyciu. Inne, warte wspomnienia frameworki to m.in. blueprint i YUI Grid.
  • Wykorzystanie Frameworków JS – frameworki JS podobnie jak te CSS-owe, pozwalają deweloperom tworzyć kod, który zadziała w różnych przeglądarkach. Tutaj z kolei polecam JQuery oraz YUI.
  • Wykorzystanie wyszukiwarek – to jest rozwiązanie, które z reguły daje odpowiedź na większość problemów. Lata obecności IE6 na ryku sprawiły, że chyba wszystkie problemy jakie ta przeglądarka sprawia zostały już opisane w Internecie. Pozostaje więc poszukać rozwiązania.

Chociaż IE6 jest przeglądarką, której większość z nas nie używała od bardzo bardzo dawna to jednak warto pamiętać o jej użytkownikach podczas tworzenia swojej WWW. Tym bardziej, że jak podaje ranking.pl, w Polsce ponad 10% internautów korzysta z tej przeglądarki. To bardzo dużo.

04. September 2009 by restless_being
Categories: Uncategorized | Tags: | Leave a comment

Xubuntu 9.04 i mobilny internet

Po kilku latach mniej lub bardziej bolesnych doświadczeń związanych z używaniem, w systemach z rodziny *buntu, urządzeń pozwalających na dostęp do tzw. mobilnego internetu nareszcie nastąpił przełom. Po tym jak zainstalowałem Xubuntu 9.04 (Jaunty Jackalope) cała konfiguracja połączenia z Siecią ograniczyła się do podania numeru PIN.

Internet jest wszędzie, ale czy również na Linuxie?

Swą przygodę z mobilnym internetem zaczynałem od modemu Option Globetrotter podłączanego do komputera przez gniazdo PCIMCIA i wszelkimi siłami broniącego się przed uruchomieniem na Linuxie (Kubuntu 6.06). W systemie Windows wystarczyło zainstalować dostarczone przez dostawcę oprogramowanie i modem działał jak należy. Tymczasem, zmuszemie modemu do poprawnego funkcjonowania w Kubuntu wymagało kilku godzin, a może nawet dni, walki ze sterownikami i konfiguracją. Napisałem sobie nawet kilkustronicowy tutorial, żeby pamiętać jak to wszystko składać do kupy.

Potem był modem Merlin XU 870 na złączu Express Card i nowsze wersje Kubuntu (7.10 i 8.04). Modem nie wymagał już kombinowania ze sterownikami, natomiast musiałem przygotować sobie sprytny skrypt pozwalający na zainicjowanie modemu, a także odpowiednią dla mojego dostawcy Internetu konfigurację KPPP (programu do łączenia się przez dial-up).

Czasy się jednak zmieniają, a systemy z rodziny *buntu razem z nimi i to na lepsze. Dzięki tym zmianom można wreszcie szybko i sprawnie skonfigurować połączenie z internetem i to na różne sposoby. Przydaje się to zwłaszcza po reinstalacji systemu, gdy chcemy jak najszybciej doprowadzić system do stanu używalności, a więc dokonać akutalizacji pakietów, zagrać w gry online takie jak partypoker, pobrać muzykę i filmy lub po prostu skontaktować ze znajomymi na jabberze, gadu-gadu lub IRCu. Zapraszam więc do dalszej części artykułu po dobre wiadomości.

Mobilny internet także w Linuxie

Niedawno zmieniłem wersję systemu operacyjnego z Kubuntu 8.04 na Xubuntu 9.04, doinstalowałem sobie także do niego pakiet Blueman będący bardzo przyjemnym managerem Bluetooth, który świetnie integruje się z Network Managerem.

Konfiguracja połączenia z Internetem (nadal modem Merlin XU 870) wymagała jedynie dodania w Network Managerze połącznia dial-up dla wskazanego operatora (dostępni są: ERA, Heyah, Idea, iPlus, Orange, Play Online, Polkomtel) i podania kodu PIN. Potem, po włożeniu modemu do gniazda w komputerze, połączenie automatycznie pokazało się w Network Managerze – wystarczyło na nim kliknąć aby uzyskać dostęp do Internetu.

Druga sprawa to to do czego był mi potrzebny Blueman. Otóż, postanowiłem sprawdzić możliwość łączenia się z Internetem za pośrednictwem telefonu. W tym celu przełożyłem kartę SIM z modemu do telefonu i korzystając z Bluemana sparowałem przez bluetooth telefon z komputerem. Potem w managerze Bluemana wskazałem mój telefon i wybrałem opcję połączenie dial-up. Skutkiem tego działania było pojawienie się w Network Managerze połączenia – tego samego, które wcześniej skonfigurowałem na potrzeby modemu. Po wybraniu tego połączenia uzyskałem dostęp do Internetu.

Łatwiej niż w Windows

Jestem mile zaskoczony tym jak łatwo można się łączyć z mobilnym internetem na Xubuntu (i zapewne też innych *buntu). Jest to nawet prostsze niż w Windows, bo nie trzeba nic instalować (prócz Bluemana jeśli ktoś zechce połączyć się poprzez bluetooth i komórkę). Jeszcze jeden powód do tego aby używać Linuxa :D

21. August 2009 by restless_being
Categories: Uncategorized | Tags: | Leave a comment

← Older posts

Newer posts →