Django: Nasazování projektu

Vytvořením projektu naše práce nekončí. Je potřeba ho zpřístupnit světu a poté udržovat. Ukážeme si nezbytné kroky při nasazování projektu a několik možných konfigurací webového serveru.
Seriál: Hrajeme si s Djangem (16 dílů)
- Django: Úvod a instalace 14. 8. 2009
- Django: Nastavení projektu a první pokusy 21. 8. 2009
- Django: Databázový model 28. 8. 2009
- Django: Databázový model podruhé 4. 9. 2009
- Django: Administrace 11. 9. 2009
- Django: Prezentace dat 18. 9. 2009
- Django: Prezentace dat podruhé 25. 9. 2009
- Django: Zpracovávání formulářů 2. 10. 2009
- Django: Autentizace a autorizace 9. 10. 2009
- Django: Nahrávání souborů 16. 10. 2009
- Django: Zabudované aplikace 23. 10. 2009
- Django: Rozšiřování možností Djanga 30. 10. 2009
- Django: Internacionalizace 6. 11. 2009
- Django: Nasazování projektu 13. 11. 2009
- Django: Kešování a škálování 20. 11. 2009
- Django: Závěr 27. 11. 2009
Při provozování projektu mimo náš vývojářský počítač je potřeba změnit několik nastavení.
Konfigurace
Režim ladění projektu nastavují v konfiguračním souboru settings.py
dvě konstanty: DEBUG
a TEMPLATE_DEBUG
. Druhá konstanta se týká výpisu chyb v šablonách. Při provozování produkčního („ostrého“) serveru je potřeba konstanty změnit na hodnotu False
, jinak se uživatelům budou při zadání neexistujicí adresy stránky nebo chybě aplikace zobrazovat ladící informace včetně výpisu zdrojového kódu. Navíc, při vypnutém ladění se posílají automaticky upozornění o chybách aplikací administrátorům stránky, pokud jsou uvedeni v konstantě ADMINS
. Konstanta SEND_BROKEN_LINK_EMAILS zprovozňuje podobnou funkci týkající se neexistujících adres. Nastavení projektu mimo ladící server by mělo vypadat například takto:
DEBUG = False TEMPLATE_DEBUG = DEBUG ADMINS = ( ('Pavel Dvořák', 'id@dqd.cz'), )
Chybové stránky
Při již zmiňovaném zadání neexistující stránky nebo chybě aplikace by se návštěvníkovi měla zobrazit stránka se smysluplnou hláškou o chybě. Šablonu s popisem chyby 404 (stránka nenalezena) je potřeba umístit do souboru templates/404.html
:
{% extends "base.html" %} {% load i18n %} {% block content %} <h1>{% block title %}{% trans "Chyba" %} 404{% endblock %}</h1> <p>{% trans "Soubor nenalezen." %}</p> {% endblock %}
Stejně tak je dobrým nápadem vytvořit soubor templates/500.html
pro výpis chyby 500 (interní chyba serveru):
{% extends "base.html" %} {% load i18n %} {% block content %} <h1>{% block title %}{% trans "Chyba" %} 500{% endblock %}</h1> <p>{% trans "Omlouváme se, ale v aplikaci došlo k neočekávané chybě. Zároveň byl odeslán upozorňující e-mail administrátorovi, takže problém brzy napravíme." %}</p> {% endblock %}
Kdybyste náhodou potřebovali pro chybu 500 specifikovat vlastní pohled, dá se to zařídit pomocí proměnné handler500.
Statické soubory
Na konci druhého dílu seriálu jsme se zmiňovali o statických souborech. Při ostrém nasazení je nejlepší nechat tato data servírovat přímo serverem z jiné domény. Lze využít poddoménu (např. media.example.cz
), pro větší projekty se často registruje pro tento účel zvlášť vlastní doména. Důvodem pro zakoupení další domény je fakt, že webový prohlížeč nebude na tuto doménu posílat cookies, takže se tak často zrychlí načítání statického obsahu.
Pro nás to znamená přenastavení proměnných MEDIA_ROOT
, MEDIA_URL
a případně ADMIN_MEDIA_PREFIX
(statické soubory administračního rozhraní). Budeme předpokládat, že se statické soubory budou nacházet na adrese http://media.example.cz/
, fyzicky budou uloženy v adresáři /var/www/media/
a statické soubory administrace v podadresáři /var/www/media/admin/
. Nastavení ovlivněných konstant vypadá takto:
MEDIA_ROOT = '/var/www/media/' MEDIA_URL = 'http://media.example.cz/' ADMIN_MEDIA_PREFIX = 'http://media.example.cz/admin/'
Samozřejmě je potřeba také založit adresář /var/www/media/
a zkopírovat do něj adresář se statickými soubory administrace ( /usr/lib/python2.5/site-packages/django/contrib/admin/media
), případně na něj vytvořit symbolický odkaz (v obou případech se výsledný adresář musí jmenovovat admin
). Správně nastavený webový server (např. Apache nebo lighttpd) poté bude automaticky servírovat tyto soubory z poddomény. Toto nastavení může vypadat kupříkladu takto:
<VirtualHost *:80> ServerName media.example.cz DocumentRoot /var/www/media/ </VirtualHost>
Nasazování nového kódu pomocí skriptu
Typické rozvržení práce na webovém projektu vypadá tak, že pracujeme na lokálním vývojovém serveru a když jsme s výsledkem spokojeni, aktualizujeme kód na produkčním serveru. To můžeme udělat buď prostým přepsáním všech souborů, nebo lépe pomocí verzovacího systému. V případě centralizovaného verzovacího systému (např. SVN, CVS) soubory nahrajeme do repozitáře serveru, u decentralizovaného systému (např. Git, Darcs) si udržujeme repozitář i u sebe.
Ať už kód aktualizujeme jakkoliv, je vhodné si vytvořit skript, který celou proceduru nasazování nového kódu automatizuje. Jedinou výjimkou je změna databázového modelu, to Django samo o sobě nezvladá a musíme rozvržení tabulek upravit ručně (SQL příkaz ALTER TABLE
) nebo použít nějaký z existujících projektů řešících tento problém. A co by takový skript měl obsahovat?
- Vytvoření kopie souboru
settings.py
. - Přepsání konfiguračních konstant
DEBUG
,MEDIA_ROOT
,MEDIA_URL
,ADMIN_MEDIA_PREFIX
,TEMPLATE_DIRS
a případněDATABASE_NAME
, pokud používáme databázi SQLite. - Aktualizování souborů pomocí vzdáleného kopírování nebo verzovacího systému (včetně statických souborů).
- Nastavení správných přístupových práv u aktualizovaných souborů.
- Úprava tabulek v případě změny nějakého z modelů.
- Restartování produkčního webserveru.
- Obnovení předchozí verze souboru
settings.py
z kopie.
U velkých projektů doporučuji produkční webserver před kopírováním odstavit, aby náhodou nedošlo k načtení nesmyslné kombinace starého a nového kódu. Soubor settings.py
lze také přepsat do univerzálnější podoby, kdy kupříkladu pomocí funkce gethostname určujeme jiné nastavení pro produkční a vývojový server. Tím by odpadl první, druhý a sedmý bod nasazování.
Serverová řešení
Existují mnoho různých variant nasazení Djanga, zaměřím se pouze na tři nejčastější. U všech předpokládám, že používáte webserver Apache a že je projekt uložený v adresáři /var/www/hrajeme_si/
. Výchozí nastavení pro doménu example.cz může vypadat kupříkladu takto:
<VirtualHost *:80> ServerName example.cz ServerAlias www.example.cz DocumentRoot /var/www/ </VirtualHost>
Modul mod_python
Tento modul není už delší dobu vyvíjený, přesto je asi nejčastěji využívaný. Stačí v nadřazeném adresáři projektu ( /var/www/
) vytvořit soubor .htaccess
s tímto obsahem:
SetHandler python-program PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE hrajeme_si.settings PythonDebug Off
Modul mod_wsgi
Toto je novější a v současnosti doporučovaný modul. V prvním kroku je potřeba přidat do části VirtualHost
v nastavení webového serveru řádek s umístěním wsgi skriptu:
WSGIScriptAlias / /var/www/hrajeme_si/hrajeme_si.wsgi
A poté do tohoto souboru zapsat následující nastavení:
import os, sys sys.path.append('/var/www/') os.environ['DJANGO_SETTINGS_MODULE'] = 'hrajeme_si.settings' from django.core.handlers import wsgi application = wsgi.WSGIHandler()
Modul FastCGI
Poslední často používanou možností je spustit Django jako CGI skript pomocí modulu FastCGI. Kromě samotného modulu je potřeba pro správnou funkci pythonový balík flup
a mít také povolený modul mod_rewrite
. Opět je potřeba přidat do části VirtualHost
několik řádků:
FastCGIExternalServer hrajeme_si/hrajeme_si.fcgi -socket hrajeme_si/hrajeme_si.sock RewriteEngine On RewriteRule ^/(.*)$ /hrajeme_si/hrajeme_si.fcgi/$1 [QSA,L]
Poté jenom stačí vytvořit soubor /var/www/hrajeme_si/hrajeme_si.fcgi
s tímto obsahem:
#!/usr/bin/python import os, sys sys.path.append('/var/www/') os.environ['DJANGO_SETTINGS_MODULE'] = "hrajeme_si.settings" from django.core.servers.fastcgi import runfastcgi runfastcgi(method='threaded', daemonize='false')
Tento soubor musí mít nastavená práva pro spuštění ( chmod +x /var/www/hrajeme_si/hrajeme_si.fcgi
).
Související odkazy
- Nasazování projektu na Djangoproject.com
- Dvanáctá kapitola v The Definitive Guide to Django
Příště si řekneme něco o kešování a škálování velkých projektů.
Narazil jsem na wiki, která se zabývá nasazováním Djanga, nachází tam několik zajímavých informací: http://djangoinproduction.com/
Ono je celkem elegantni, ze WSGI umoznuje v konfiguraku prepsat, jake settins.py se bude pouzivat, takze pro ladeni se da pouzivat normalne settings.py a pro ostre nasazeni treba wsgi_settings.py a tak neni potreba nic slozite upravovat a nebo vyhodnocovat hostname.
Obávám se, že si tím jenom přivodíme další problém – budeme muset udržovat více souborů s nastavením. To je věc, které se já osobně snažím vyhnout.