iDreamMicro - Mot-clé - Apache2023-05-17T23:19:49+02:00Julien Le Sechurn:md5:748efb83ba33c51f389cc9cd76987761DotclearDjango, Apache 2 et les fichiers statiquesurn:md5:a228525d7c65d71a1929157d776a34dd2013-10-17T08:00:00+02:002013-10-31T18:21:32+01:00Julien Le SechApacheDjangoPython<p>
On désigne par fichiers statiques des fichiers additionnels tels que des images, des feuilles de style CSS ou encore des fichiers JavaScript. Django est capable de les prendre en charge, cependant il est nécessaire de configurer l'application ainsi que le serveur virtuel Apache.
</p>
<p>
L'utilisation de fichiers statiques depuis un projet Django n'est pas compliquée en soit, mais la moindre erreur de configuration peut rapidement virer au casse tête. Cet article propose un pas à pas le plus simple possible pour y parvenir.
</p>
<p>
Plutôt que de repartir de zéro, on reprendra comme base le projet de l'article précédent : <a href="http://www.idreammicro.com/post/django-apache-2-mod-wsgi-maj">Django, Apache 2 et le module WSGI</a>.
</p> <h2>Vue</h2>
<p>
Au lieu de retourner une réponse HTTP, la vue <em>index</em> affiche un <em>template</em> au format HTML. On modifie le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/views.py?p=6"><em>helloworld/views.py</em></a>
</p>
<pre class="brush: python;" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/views.py?p=6>helloworld/views.py</a>">
from django.shortcuts import render
def index(request):
return render(request, 'helloworld/index.html')
</pre>
<h2>Templates</h2>
<p>
Conformément aux <a href="https://docs.djangoproject.com/en/1.5/intro/tutorial03/">préconisations</a> de la documentation Django, on crée un dossier <em>helloworld/templates/helloworld</em> afin de recevoir les <em>templates</em> de l'application <em>helloworld</em>.
</p>
<pre class="brush: bash; gutter: false;">
mkdir -p helloworld/templates/helloworld
</pre>
<p>
Afin de faire les choses dans les règles de l'Art, on utilise le début le <a href="https://docs.djangoproject.com/en/1.5/topics/templates/#">langage de <em>template</em></a> de Django, et plus particulièrement <a href="https://docs.djangoproject.com/en/1.5/topics/templates/#template-inheritance">l'héritage de <em>template</em></a>.
</p>
<p>
On crée un <em>template</em> de base dans le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/templates/helloworld/base.html?p=6"><em>helloworld/templates/helloworld/base.html</em></a>. On notera l'inclusion de la feuille de style <em>screen.css</em> (ligne 5).
</p>
<pre class="brush: xhtml; highlight: [5];" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/templates/helloworld/base.html?p=6>helloworld/templates/helloworld/base.html</a>">
<!DOCTYPE html>
<html lang="fr">
<head>
{% load staticfiles %}
<link rel="stylesheet" type="text/css" media="screen" href="http://www.idreammicro.com/post/{% static 'helloworld/screen.css' %}" />
<title>{% block title %}Hello world!{% endblock %}</title>
</head>
<body>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
</pre>
<p>
Puis on crée un autre <em>template</em> héritant du <em>template</em> de base dans le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/templates/helloworld/index.html?p=6"><em>helloworld/templates/helloworld/index.html</em></a>.
</p>
<pre class="brush: xhtml;" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/templates/helloworld/index.html?p=6>helloworld/templates/helloworld/index.html</a>">
{% extends "helloworld/base.html" %}
{% block title %}Hello world - Index{% endblock %}
{% block content %}
<p>
Hello world!
</p>
{% endblock %}
</pre>
<h2>Fichiers statiques</h2>
<p>
Le fichier statique le plus courant est sans doute la feuille de style CSS. On propose donc d'en créer une qui se contentera de colorer les textes des paragraphes en rouge.
</p>
<p>
Conformément aux <a href="https://docs.djangoproject.com/en/1.5/intro/tutorial06/">préconisations</a> de la documentation Django, on crée un dossier <em>helloworld/static/helloworld</em> afin de recevoir les fichiers statiques de l'application <em>helloworld</em>.
</p>
<pre class="brush: bash; gutter: false;">
mkdir -p helloworld/static/helloworld
</pre>
<p>
On crée une feuille de style dans le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/static/helloworld/screen.css?p=6"><em>helloworld/static/helloworld/screen.css</em></a>.
</p>
<pre class="brush: css;" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/static/helloworld/screen.css?p=6>helloworld/static/helloworld/screen.css</a>">
p {
color: red;
}
</pre>
<p>
À la racine du projet, on crée un dossier <em>static</em> dans lequel les fichier statiques des différentes applications seront collectés.
</p>
<pre class="brush: bash; gutter: false;">
mkdir static
</pre>
<h2>Serveur virtuel</h2>
<p>
Les opérations sur le serveur virtuel nécessitent les <strong>droits d'administration</strong>.
</p>
<p>
On modifie le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/apache-vhost/idreammicro?p=6"><em>/etc/apache2/sites-available/idreammicro</em></a> afin de servir le dossier <em>static</em>.
</p>
<pre class="brush: text; first-line: [23];" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/apache-vhost/idreammicro?p=6>idreammicro</a>">
Alias /static/ /home/jlesech/www-django/idreammicro/static/
<Location "/static/">
Options -Indexes
</Location>
</pre>
<p>
On recharge le serveur virtuel.
</p>
<pre class="brush: bash; gutter: false;">
service apache2 reload
</pre>
<h2>Collecte des fichiers statiques</h2>
<p>
On modifie le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/settings.py?p=6"><em>idreammicro/settings.py</em></a> afin d'indiquer le dossier dans lequel les fichiers statiques seront collectés.
</p>
<p>
Afin de rendre le projet le plus maintenable possible, on définit une variable <em>PROJECT_ROOT</em> indiquant le dossier racine (ligne 4).
</p>
<pre class="brush: python; highlight: [3, 4];" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/settings.py?p=6>idreammicro/settings.py</a>">
# Django settings for idreammicro project.
import os
PROJECT_ROOT = os.path.dirname(__file__) + '/..'
</pre>
<p>
Puis on renseigne la variable <em>STATIC_ROOT</em> (ligne 67), relativement à la racine.
</p>
<pre class="brush: python; first-line: 63; highlight: [67];" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/settings.py?p=6>idreammicro/settings.py</a>">
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/var/www/example.com/static/"
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
# URL prefix for static files.
# Example: "http://example.com/static/", "http://static.example.com/"
STATIC_URL = '/static/'
</pre>
<p>
On lance la <a href="https://docs.djangoproject.com/en/1.5/ref/contrib/staticfiles/#collectstatic">collecte des fichiers statiques</a>. Plutôt que de les copier, on ordonne la création de liens symboliques avec l'option <em>--link</em>.
</p>
<pre class="brush: bash; gutter: false;">
python manage.py collectstatic --link
</pre>
<p>
Après la collecte, on doit retrouver des liens vers les fichiers statiques dans le dossier <em>static</em>. Ceux-ci sont organisés de la même manière que dans l'application <em>helloworld</em>.
</p>
<pre class="brush: text; gutter: false; highlight: [19, 20, 21];" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro?p=6>Arboresence</a>">
idreammicro
|_ helloworld
| |_ static
| | |_ helloworld
| | |_ screen.css
| |_ templates
| | |_ helloworld
| | |_ base.html
| | |_ index.html
| |_ __init__.py
| |_ models.py
| |_ tests.py
| |_ views.py
|_ idreammicro
| |_ __init.py__
| |_ settings.py
| |_ urls.py
| |_ wsgi.py
|_ static
| |_ helloworld
| |_ screen.css
|_ manage.py
</pre>
<h2>Conclusion</h2>
<p>
Nous y sommes, il est temps de vérifier que ce célèbre <em>Hello world!</em> s'affiche désormais en rouge ! On saisit l'adresse <a href="http://django/helloworld">http://django/helloworld</a> dans un navigateur et...
</p>
<p>
<a href="http://www.idreammicro.com/public/posts/django-apache-static/helloworld.png" title="helloworld.png"><img src="http://www.idreammicro.com/public/posts/django-apache-static/helloworld.png" alt="helloworld.png" style="margin: 0 auto; display: block;" title="helloworld.png, oct. 2013" /></a>
</p>
<p>
... <em>Hello world!</em> est bien coloré en rouge !
</p>
<h2>Références</h2>
<ul>
<li><a href="https://docs.djangoproject.com/en/1.5/intro/tutorial03/">Django Documentation - Writing your first Django app, tutorial part 3</a></li>
<li><a href="https://docs.djangoproject.com/en/1.5/intro/tutorial06/">Django Documentation - Writing your first Django app, tutorial part 6</a></li>
<li><a href="https://docs.djangoproject.com/en/1.5/topics/templates/#">Django Documentation - The Django template language</a></li>
<li><a href="https://docs.djangoproject.com/en/1.5/howto/static-files/">Django Documentation - Managing static files (CSS, images)</a></li>
<li><a href="https://docs.djangoproject.com/en/1.5/ref/contrib/staticfiles/#collectstatic">Django Documentation - The staticfiles app</a></li>
</ul>http://www.idreammicro.com/post/Django-apache2-fichiers-statiques#comment-formhttp://www.idreammicro.com/feed/atom/comments/61Django, Apache 2 et module WSGI (mise à jour)urn:md5:6576d295250b2ce98fa82971a871b7752013-10-12T18:50:00+02:002014-04-22T17:30:54+02:00Julien Le SechApacheDjangoPython<p>
Comme le bon vin, <a href="https://www.djangoproject.com/">Django</a> se bonifie avec le temps. Mieux encore, il se simplifie ! C'est notamment le cas pour son intégration avec <a href="http://httpd.apache.org/">Apache 2</a> via le <a href="http://code.google.com/p/modwsgi/">module WSGI</a>.
</p>
<p>
Un <a href="http://www.idreammicro.com/post/django-apache2-wsgi">précédent article</a> proposait une démarche permettant de servir une application Django 1.3 avec Apache 2 et le module WSGI. Depuis, Django est passé en version 1.4 puis 1.5. L'occasion de remettre ça !
</p>
<p>
L'environnement utilisé pour cet article repose sur la distribution <a href="http://www.debian.org/">Debian Wheezy 7.1 amd64</a>. On y a ajouté les paquets <a href="http://packages.debian.org/wheezy/apache2">apache2</a>, <a href="http://packages.debian.org/wheezy/libapache2-mod-wsgi">libapache2-mod-wsgi</a> et <a href="https://pypi.python.org/pypi/Django/1.5.4">Django 1.5.4</a>.
</p> <h2>Création du projet et de l'application</h2>
<p>
On choisit arbitrairement de travailler dans le dossier <em>/home/jlesech/www-django</em>. <strong>À chacun de l'adapter en fonction de son environnement</strong>.
</p>
<p>
On crée un projet nommé <em>idreammicro</em>.
</p>
<pre class="brush: bash; gutter: false;">
django-admin.py startproject idreammicro
</pre>
<p>
On se place dans le dossier du projet. <strong>Tous les chemins cités dans la suite de cet article seront relatifs à cet emplacement.</strong>.
</p>
<pre class="brush: bash; gutter: false;">
cd idreammicro
</pre>
<p>
Puis on crée une application nommée <em>helloworld</em>.
</p>
<pre class="brush: bash; gutter: false;">
django-admin.py startapp helloworld
</pre>
<p>
Il en résulte l'arborescence suivante, introduite avec <a href="https://docs.djangoproject.com/en/1.5/releases/1.4/#updated-default-project-layout-and-manage-py">Django 1.4</a>.
</p>
<pre class="brush: text; gutter: false;" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro?p=3>Arboresence</a>">
idreammicro
|_ helloworld
| |_ __init__.py
| |_ models.py
| |_ tests.py
| |_ views.py
|_ idreammicro
| |_ __init.py__
| |_ settings.py
| |_ urls.py
| |_ wsgi.py
|_ manage.py
</pre>
<h3>Support WSGI</h3>
<p>
Django 1.4 a introduit une <a href="https://docs.djangoproject.com/en/1.5/releases/1.4/#improved-wsgi-support">amélioration du support WSGI</a>, en embarquant une application WSGI dans le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/wsgi.py?p=4"><em>idreammicro/wsgi.py</em></a>.
</p>
<pre class="brush: python;" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/wsgi.py?p=4>idreammicro/wsgi.py</a>">
"""
WSGI config for idreammicro project.
This module contains the WSGI application used by Django's development server
and any production WSGI deployments. It should expose a module-level variable
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
this application via the ``WSGI_APPLICATION`` setting.
Usually you will have the standard Django WSGI application here, but it also
might make sense to replace the whole Django WSGI application with a custom one
that later delegates to the Django one. For example, you could introduce WSGI
middleware here, or combine a Django application with an application of another
framework.
"""
import os
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
# if running multiple sites in the same mod_wsgi process. To fix this, use
# mod_wsgi daemon mode with each site in its own daemon process, or use
# os.environ["DJANGO_SETTINGS_MODULE"] = "idreammicro.settings"
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "idreammicro.settings")
# This application object is used by any WSGI server configured to use this
# file. This includes Django's development server, if the WSGI_APPLICATION
# setting points here.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
# Apply WSGI middleware here.
# from helloworld.wsgi import HelloWorldApplication
# application = HelloWorldApplication(application)
</pre>
<h3>Activation de l'application</h3>
<p>
Dans le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/settings.py?p=4"><em>idreammicro/settings.py</em></a>, on active l'application <em>helloworld</em> (ligne 127).
</p>
<pre class="brush: python; first-line: 116; highlight: [127];" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/settings.py?p=4>idreammicro/settings.py</a>">
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'helloworld',
)
</pre>
<h3>Vue</h3>
<p>
Dans le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/views.py?p=4"><em>helloworld/views.py</em></a>, on crée la vue <em>index</em>.
</p>
<pre class="brush: python;" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/views.py?p=4>helloworld/views.py</a>">
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello world!")
</pre>
<p>
Celle-ci se veut la plus simple possible et affiche un simple <em>Hello world!</em>.
</p>
<h3><em>Urls</em></h3>
<p>
On crée le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/urls.py?p=4"><em>helloworld/urls.py</em></a>, on configure l'<em>url</em> de la vue <em>index</em> précédemment créée.
</p>
<pre class="brush: python;" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/helloworld/urls.py?p=4>helloworld/urls.py</a>">
from django.conf.urls import patterns, url
from helloworld import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index')
)
</pre>
<p>
Dans le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/urls.py?p=4"><em>idreammicro/urls.py</em></a>, on inclut le fichier contenant les <em>urls</em> de l'application <em>helloworld</em>.
</p>
<pre class="brush: python; highlight: [18];" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/idreammicro/urls.py?p=4>idreammicro/urls.py</a>">
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'idreammicro.views.home', name='home'),
# url(r'^idreammicro/', include('idreammicro.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
# url(r'^admin/', include(admin.site.urls)),
url(r'^helloworld/', include('helloworld.urls')),
)
</pre>
<p>
Afin de vérifier que le projet et l'application sont fonctionnels, on lance le serveur de développement.
</p>
<pre class="brush: bash; gutter: false;">
python manage.py runserver
</pre>
<p>
Dans un navigateur, on saisit l'adresse <a href="http://localhost:8000/helloworld">http://localhost:8000/helloworld</a>.
</p>
<p>
<a href="http://www.idreammicro.com/public/posts/django-apache2-maj/helloworld.png" title="helloworld.png"><img src="http://www.idreammicro.com/public/posts/django-apache2-maj/helloworld.png" alt="helloworld.png" style="margin: 0 auto; display: block;" title="helloworld.png, oct. 2013" /></a>
</p>
<p>
Magnifique ! Le projet et l'application fonctionnent. On peut maintenant passer aux choses sérieuses et les servir à l'aide d'Apache.
</p>
<h2>Virtual Host Apache</h2>
<p>
On choisit de créer un <a href="http://httpd.apache.org/docs/trunk/fr/mod/core.html#virtualhost">serveur virtuel</a> dédié au projet Django. <strong>Les opérations suivantes nécessitent d'avoir les droits d'administration</strong>.
</p>
<p>
On crée le fichier <a href="http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/apache-vhost/idreammicro?p=4"><em>/etc/apache2/sites-available/idreammicro</em></a>.
</p>
<pre class="brush: text;" title="<a href=http://svn.idreammicro.com/blog-sources/django-apache2-wsgi-2/idreammicro/apache-vhost/idreammicro?p=4>Serveur virtuel idreammicro</a>">
<VirtualHost *:80>
ServerName django
ServerAlias django
DocumentRoot /home/jlesech/www-django/idreammicro
<Directory /home/jlesech/www-django/idreammicro>
Order allow,deny
Allow from all
</Directory>
WSGIDaemonProcess django processes=2 threads=15 display-name=%{GROUP} python-path=/home/jlesech/www-django/idreammicro
WSGIProcessGroup django
WSGIScriptAlias / /home/jlesech/www-django/idreammicro/idreammicro/wsgi.py
<Directory /home/jlesech/www-django/idreammicro/idreammicro>
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/idreammicro_error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/idreammicro_access.log combined
</VirtualHost>
</pre>
<p>
On active le nouveau serveur virtuel.
</p>
<pre class="brush: bash; gutter: false;">
a2ensite idreammicro
</pre>
<p>
Dans le fichier <em>/etc/hosts</em>, on ajoute un <em>host</em> (ligne 3).
</p>
<pre class="brush: text; highlight: [3];">
127.0.0.1 localhost
127.0.1.1 i7
127.0.0.1 django
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
</pre>
<p>
Dans un navigateur, on saisit l'adresse <a href="http://django/helloworld">http://django/helloworld</a>.
</p>
<p>
<a href="http://www.idreammicro.com/public/posts/django-apache2-maj/helloworld2.png" title="helloworld2.png"><img src="http://www.idreammicro.com/public/posts/django-apache2-maj/helloworld2.png" alt="helloworld2.png" style="margin: 0 auto; display: block;" title="helloworld2.png, oct. 2013" /></a>
</p>
<h2>Conclusion</h2>
<p>
Comme l'avait montré le <a href="http://www.idreammicro.com/post/django-apache2-wsgi">précédent article</a>, servir un projet Django avec Apache et le module WSGI était déjà relativement simple. C'est encore plus simple aujourd'hui !
</p>
<p>
Par rapport à Django 1.3, Django 1.4 et ses versions supérieures nous épargnent la création de l'application WSGI. Ainsi on se concentre sur la partie spécifique à chaque serveur, en l'occurrence la création d'un serveur virtuel Apache dédié au projet Django.
</p>
<h2>Références</h2>
<ul>
<li><a href="https://docs.djangoproject.com/en/1.5/howto/deployment/wsgi/">Django Documentation - How to deploy with WSGI</a></li>
<li><a href="https://docs.djangoproject.com/en/1.5/howto/deployment/wsgi/modwsgi/">Django Documentation - How to use Django with Apache and mod_wsgi</a></li>
<li><a href="http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Delegation_To_Daemon_Process">Quick configuration guide for mod_wsgi</a></li>
</ul>
<h2>Sujets relatifs</h2>
<ul>
<li><a href="http://www.idreammicro.com/post/django-apache2-wsgi">Django, Apache 2 et module WSGI</a></li>
<li><a href="http://www.idreammicro.com/post/django-chartit">Chartit, ou des graphiques avec Django</a></li>
</ul>http://www.idreammicro.com/post/django-apache-2-mod-wsgi-maj#comment-formhttp://www.idreammicro.com/feed/atom/comments/56Django, Apache 2 et module WSGIurn:md5:f2538460dae542d32d8102861b7fe5962012-03-13T12:00:00+01:002013-10-13T13:31:29+02:00Julien Le SechApacheDjangoPython<p>
<a href="https://www.djangoproject.com/">Django</a> est un <em>framework</em> web de haut niveau développé en <a href="http://www.python.org">Python</a> dont le but est d'encourager le développement web rapide, propre et simple. Django est libre et publié sous <a href="http://fr.wikipedia.org/wiki/Licence_BSD"><acronym title="Berkeley Software Distribution license">licence BSD</acronym></a>.
</p>
<p>
Bien que Django embarque un serveur, celui-ci est à réserver au développement. En effet il n'est pas prévu pour faire office de serveur de production. Cet article propose de servir un site Django à l'aide d'<a href="http://www.apache.org/">Apache 2</a> et du module <a href="http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface"><acronym title="Web Server Gateway Interface">WSGI</acronym></a>.
</p>
<p>
Si de nombreux articles sur ce sujet sont disponibles sur Internet, peu se contentent du strict minimum. Assez souvent il s'agit même de configurations alambiquées dans lesquelles on se perd, avant de laisser tomber... Cet article propose une configuration minimale qui, même si elle n'est peut-être pas optimale, a au moins le mérite d'être accessible au plus grand nombre.
</p> <h2>Pré-requis</h2>
<p>Le système d'exploitation utilisé est <a href="http://www.ubuntu.com/">Ubuntu 10.04.3 LTS x64</a>.</p>
<p>Les paquets suivants sont requis :</p>
<ul>
<li><a href="http://packages.ubuntu.com/lucid/httpd/apache2">apache2</a> ;</li>
<li><a href="http://packages.ubuntu.com/lucid/libapache2-mod-wsgi">libapache2-mod-wsgi</a> ;</li>
<li><a href="http://packages.ubuntu.com/lucid/python">python</a> ;</li>
<li><a href="http://packages.ubuntu.com/lucid/python-django">python-django</a>.</li>
</ul>
<p>
On installe les paquets :
</p>
<pre class="brush: bash; gutter: false;">
~$ sudo apt-get install apache2 libapache2-mod-wsgi python python-django
</pre>
<h2>Création du site Django</h2>
<p>
Le projet <em>idreammicro</em> servant de support à cet article se situe dans le dossier <em>/var/www/idreammicro</em>. L'application se nomme <em>helloworld</em>. L'arborescence est donc la suivante :
</p>
<pre class="brush: text; gutter: false;">
/var/www/
|_idreammicro
|_helloworld
</pre>
<h3>Création du projet <em>idreammicro</em></h3>
<p>On se place dans le dossier accueillent les sites web par défaut <em>/var/www</em> :</p>
<pre class="brush: bash; gutter: false;">
~$ cd /var/www
</pre>
<p>On crée un projet Django nommé <em>idreammicro</em> :</p>
<pre class="brush: bash; gutter: false;">
/var/www$ sudo django-admin startproject idreammicro
</pre>
<p>Les fichiers suivants sont créés dans le dossier <em>/var/www/idreammicro</em> :</p>
<ul>
<li><em>__init__.py</em> ;</li>
<li><em>manage.py</em> ;</li>
<li><em>settings.py</em> ;</li>
<li><em>urls.py</em>.</li>
</ul>
<p>On se place dans le dossier du projet :</p>
<pre class="brush: bash; gutter: false;">
/var/www$ cd idreammicro/
</pre>
<p>On vérifie que le projet est correctement créé en lançant le serveur de développement intégré à Django :</p>
<pre class="brush: bash; gutter: false;">
/var/www/idreammicro$ python manage.py runserver
</pre>
<p>Si tout se passe bien, le message suivant apparaît dans la console :</p>
<pre class="brush: text; gutter: false;">
Validating models...
0 errors found
Django version 1.1.1, using settings 'idreammicro.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
</pre>
<p>
La console nous informe que le serveur de développement Django est accessible à l'adresse <em>http://127.0.0.1:8000</em>. Si on ouvre le lien, la page ci-dessous doit s'afficher.
</p>
<p>
<a href="http://www.idreammicro.com/public/posts/django-apache2/project.png" title="project.png"><img src="http://www.idreammicro.com/public/posts/django-apache2/project.png" alt="project.png" style="margin: 0 auto; display: block;" title="project.png, mar. 2012" /></a>
</p>
<h3>Création de l'application <em>helloworld</em></h3>
<p>On crée une application nommée <em>helloworld</em> :</p>
<pre class="brush: bash; gutter: false;">
/var/www/idreammicro$ sudo python manage.py startapp helloworld
</pre>
<p>Les fichiers suivants sont créés dans le dossier <em>/var/www/idreammicro/helloworld</em> :</p>
<ul>
<li><em>__init__.py</em> ;</li>
<li><em>models.py</em> ;</li>
<li><em>tests.py</em> ;</li>
<li><em>views.py</em>.</li>
</ul>
<p>
Il est nécessaire d'ajouter l'application <em>helloworld</em> à la liste des applications du projet <em>idreammicro</em>. Pour ce faire on édite le fichier <em>settings.py</em> et on ajoute l'application <em>helloworld</em> à la liste des applications installées :
</p>
<pre class="brush: python; first-line: 74; highlight: [79];" title="<a href=/public/posts/django-apache2/settings.py>settings.py</a>">
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'helloworld'
)
</pre>
<p>
Il est nécessaire de créer une vue. On édite le fichier <em>helloworld/views.py</em>. On y ajoute la vue <em>index</em> :
</p>
<pre class="brush: python;" title="<a href=/public/posts/django-apache2/views.py>views.py</a>">
# Create your views here.
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello world! You're at the index.")
</pre>
<p>
Il est nécessaire de faire pointer au moins une <a href="http://fr.wikipedia.org/wiki/Uniform_Resource_Locator"><acronym title="Uniform Resource Locator">URL</acronym></a> sur la vue <em>index</em>. Dans le fichier <em>urls.py</em>, on ajoute deux URLs pointant sur la vue <em>index</em> (lignes 10 et 11) :
</p>
<pre class="brush: python; highlight: [10, 11];" title="<a href=/public/posts/django-apache2/urls.py>urls.py</a>">
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^idreammicro/', include('idreammicro.foo.urls')),
(r'^$', 'helloworld.views.index'),
(r'^helloworld/$', 'helloworld.views.index'),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
# (r'^admin/', include(admin.site.urls)),
)
</pre>
<p>
Ainsi les adresses <em>http://127.0.0.1:8000</em> et <em>http://127.0.0.1:8000/helloworld</em> afficheront la même page d'index.
</p>
<p>
On relance le serveur de développement :
</p>
<pre class="brush: bash; gutter: false;">
/var/www/idreammicro$ python manage.py runserver
</pre>
<p>
On ouvre à nouveau la page <em>http://127.0.0.1:8000</em> qui doit désormais afficher ceci :
</p>
<p>
<a href="http://www.idreammicro.com/public/posts/django-apache2/application.png" title="application.png"><img src="http://www.idreammicro.com/public/posts/django-apache2/application.png" alt="application.png" style="margin: 0 auto; display: block;" title="application.png, mar. 2012" /></a>
</p>
<p>
Comme on vient de le vérifier avec le serveur de développement, le site Django <em>idreammicro</em> est désormais fonctionnel. Toutefois Django déconseille fortement d'utiliser le serveur de développement en production. C'est pourquoi cet article propose maintenant de servir le site <em>idreammicro</em> à l'aide d'Apache.
</p>
<p>
[<a href="http://www.idreammicro.com/public/posts/django-apache2/idreammicro.zip">Télécharger le projet <em>idreammicro</em></a>]
</p>
<h2>Servir le site <em>idreammicro</em> avec Apache 2</h2>
<h3>Application WSGI</h3>
<p>
Il est nécessaire de créer une application WSGI. Celle-ci sera contenue dans le fichier <em>/var/www/idreammicro/apache/django.wsgi</em>.
</p>
<p>
Dans le dossier du projet Django, on crée un dossier <em>apache</em> :
</p>
<pre class="brush: bash; gutter: false;">
/var/www/idreammicro$ sudo mkdir apache
</pre>
<p>
On crée un fichier <em>django.wsgi</em> dans le dossier précédemment créé et on y écrit le contenu suivant :
</p>
<pre class="brush: python;" title="<a href=/public/posts/django-apache2/django.wsgi>django.wsgi</a>">
import os
import sys
path = '/var/www/'
if path not in sys.path:
sys.path.append(path)
sys.path.append('/var/www/idreammicro/')
os.environ['DJANGO_SETTINGS_MODULE'] = 'idreammicro.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<h3>Création du <em>VirtualHost</em></h3>
<p>
On crée un <a href="http://httpd.apache.org/docs/2.2/fr/vhosts/"><em>VirtualHost</em></a> dédié dans le fichier <em>/etc/apache2/sites-available/idreammicro</em> :
</p>
<pre class="brush: text;" title="<a href=/public/posts/django-apache2/idreammicro>idreammicro</a>">
<VirtualHost *:80>
ServerName idreammicro
DocumentRoot /var/www/idreammicro
<Directory /var/www/idreammico>
Order allow,deny
Allow from all
</Directory>
WSGIDaemonProcess daemon user=www-data group=www-data processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup daemon
WSGIScriptAlias / /var/www/idreammicro/apache/django.wsgi
</VirtualHost>
</pre>
<p>
On indique qu'Apache (utilisateur <em>www-data</em>, groupe <em>www-data</em>) est le propriétaire de l'application Django :
</p>
<pre class="brush: bash; gutter: false;">
/var/www/idreammicro$ sudo chown -R www-data:www-data /var/www/idreammicro
</pre>
<p>
On active le site <em>idreammicro</em> :
</p>
<pre class="brush: bash; gutter: false;">
/var/www/idreammicro$ sudo a2ensite idreammicro
</pre>
<p>
On recharge la configuration d'Apache :
</p>
<pre class="brush: bash; gutter: false;">
/var/www/idreammicro$ sudo /etc/init.d/apache2 reload
</pre>
<p>
Le <em>VirtualHost</em> Apache précédemment créé porte le nom <em>idreammicro</em> (ServerName idreammicro). Par conséquent il est nécessaire de créer une nouvelle association nom de machine / adresse IP. Dans le fichier <em>/etc/hosts</em>, on ajoute la ligne :
</p>
<pre class="brush: text; gutter: false;">
127.0.1.1 idreammicro
</pre>
<h3>Vérification</h3>
<p>
On vérifie que le site <em>idreammicro</em> est bien servi par Apache en se connectant à l'adresse <em>http://idreammicro</em>. Si tout fonctionne correctement, la page correspondant à la vue <em>index</em> doit s'afficher.
</p>
<p>
<a href="http://www.idreammicro.com/public/posts/django-apache2/idreammicro.png" title="idreammicro.png"><img src="http://www.idreammicro.com/public/posts/django-apache2/idreammicro.png" alt="idreammicro.png" style="margin: 0 auto; display: block;" title="idreammicro.png, mar. 2012" /></a>
</p>
<p>
[<a href="http://www.idreammicro.com/public/posts/django-apache2/idreammicro-apache.zip">Télécharger le projet <em>idreammicro</em></a>]
</p>
<h2>Conclusion</h2>
<p>
Finalement, servir un site Django avec Apache n'est pas si compliqué, pour peu qu'on trouve la bonne méthode. Il est certainement possible de réaliser une configuration plus avancée, aussi bien concernant <a href="http://www.apache.org/">Apache</a> que le <a href="http://code.google.com/p/modwsgi/">module WSGI</a>. Leurs sites respectifs sont des mines d'informations...
</p>
<h2>Références</h2>
<ul>
<li><a href="https://docs.djangoproject.com/en/1.3/intro/tutorial01/">Writing your first Django app, part 1</a></li>
<li><a href="https://docs.djangoproject.com/en/1.3/intro/tutorial03/">Writing your first Django app, part 3</a></li>
<li><a href="https://docs.djangoproject.com/en/1.3/howto/deployment/modwsgi/">How to use Django with Apache and mod_wsgi</a></li>
<li><a href="http://blog.stannard.net.au/2010/12/11/installing-django-with-apache-and-mod_wsgi-on-ubuntu-10-04/">Installing Django with Apache and mod_wsgi on Ubuntu 10.04</a></li>
</ul>
<h2>Sujets relatifs</h2>
<ul>
<li><a href="http://www.idreammicro.com/post/django-chartit">Chartit, ou des graphiques avec Django</a></li>
<li><a href="http://www.idreammicro.com/post/django-apache-2-mod-wsgi-maj">Django, Apache 2 et module WSGI (mise à jour)</a></li>
</ul>http://www.idreammicro.com/post/django-apache2-wsgi#comment-formhttp://www.idreammicro.com/feed/atom/comments/16