/ programowanie

Django, buildout i megiteam

Podczas pisania swojego drugiego projektu w django (czyli tej strony) zacząłem się zastanawiać nad tym co będzie jeśli zaktualizuję część używanych aplikacji. Przykładowo będę miał kilka stron. W jednej apikacji coś się zmieni i wszystkie mogą przestać działać. Przecież mogę nie zdąrzyć poprawić wszystkich projektów w krótkim czasie. Dlatego zacząłem używać buildouta. Na początku natknąłem się na kilka problemów, które ujawniły się podczas uruchamiania na hostingu megiteam. Poniżej podam gotowe rozwiązanie. Może się komuś przyda.

Instalujemy buildouta na koncie.

easy_install --prefix=$HOME/.python zc.buildout

Tworzymy katalog, w którym będziemy tworzyć projekt. Dla pdzykładu wezmiemy nazwę django. Będąc w katalogu wydajemy polecenie

buildout init

Pobierze to setuptools, utworzy katalogi oraz plik buildout.cfg. Jak można się domyślić w nim będzie znajdowała się informacja o potrzebnych pakietach i konfiguracji. Nie będę opisywał tutaj jak to zrobić. Wszystko jest omówione na stronie buildouta. Poniżej wkleję mój plik konfiguracyjny.

[buildout]
parts = PIL django

[versions]
django = 1.3

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

[python2.7]
executable = /usr/local/bin/python2.7

[django]
recipe = djangorecipe
project = project
python = python2.7
eggs = PIL
    django-grappelli
    django-filebrowser
    south
    django-taggit
    django-debug_toolbar
    django-sphinx

settings = production
wsgi = false

Po zapisaniu pliku buildout.cfg wydajemy komendę

buildout

co powoduje, że wymienione oprogramowanie zostaje zainstalowane w katalogu projektu. Tego także nie będę opisywał. Jest to na tyle intuicyjne, że nawet nie trzeba dokumentacji.

Jak widać w załączonym powyżej pliku buildout.cfg mój projekt znajduje się w katalogu o nazwie project. Więc w tym przykładzie dokładnie mamy /django/project/. W katalogu project musimy ustawić scieżkę PYTHONPATH aby powiadomić, które aplikacje mają być używane. Będąc w katalogu project tworzymy plik o nazwie .environment (kropka na początku jest ważna ;-)) W pliku tym wpisujemy

PYTHONPATH=$HOME/django:$HOME/django/eggs/Django-1.3-py2.7.egg/

Zakładam tutaj oczywiście, że katalog django znajduje się w katalogu użytkownika. Jeśli w pliku konfiguracyjnym buildouta podana jest inna wersja django i pythona to także trzeba zmienić ścieżkę do django. Tego też chyba nie muszę wyjaśniać ;-)

I tutaj pojawił się mój problem. Nadal projekt nie działał. Korzystał cały czas z oprogramowania znajdującego się na serwerze i w katalogu domowym. Na ircu (#[email protected]) dowiedziałem się, że projekt www.django.pl także używa buildouta i jest trzymany na megiteam. Dominik "dominno" Szopa, który zajmuje się polskim portalem django na szczęscie zaoszczędził mi kłopotu ;-)

Rozwiązanie nie jest eleganckie ale z powodu braku możliwości uruchamiania własnych skryptów WSGI nie ma chyba innego wyjścia. Aby dokończyć uruchamianie projektu na początku pliku settings.py w projekcie django umieszczamy zawartość pliku /django/projekt/bin/django. U mnie wygląda on następująco

#!/usr/local/bin/python2.7

import sys
sys.path[0:0] = [
'/usr/local/python2.7/lib/python2.7/site-packages/PIL-1.1.7-py2.7-linux-x86_64.egg',
'/home/eshlox/www/eshlox/eggs/django_grappelli-2.3.3-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/django_filebrowser-3.3.0-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/South-0.7.3-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/django_taggit-0.9.3-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/django_debug_toolbar-0.8.5-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/django_sphinx-2.2.4-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/djangorecipe-0.99-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/Django-1.3-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/zc.recipe.egg-1.3.2-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/zc.buildout-1.5.2-py2.7.egg',
'/home/eshlox/www/eshlox/eggs/setuptools-0.6c12dev_r88846-py2.7.egg',
'/home/eshlox/www/eshlox/parts/django',
'/home/eshlox/www/eshlox',
]


import djangorecipe.manage

if __name__ == '__main__':
djangorecipe.manage.main('project.production')

W sumie mogłbym już na tym zakończyć opis. Jednak jak zwykle mi to nie wystarczyło. Przeszkadzało mi to, że w przyszłości zawartość pliku może się zmienić. Zrobię aktualizację. Zmienią się wersje i będę musiał ponownie kopiować zawartość. Mimo, że nie ma przy tym dużo pracy to znalazłem inne rozwiązanie. Zamiast przeklejać całą zawartość wystarczy w pliku settings.py wpisać na początku

import imp
imp.load_source('django', '../bin/django')

Dzięki temu nie musimy się już przejmować zmianą zawartości pliku django ponieważ będzie on dynamicznie importowany. Teraz już można cieszyć się działającym projektem w buildoucie ;-)