You are on page 1of 20

Formation Django

Contact: contact@emencia.com
Auteur: Julien Fache <fantomas42@gmail.com>
Date: 2011-06-06

Abstract

Document à usage personnel.


Résumant les étapes de la formation Django.

Sommaire

Jour 1
Introduction à Django
Ses forces
Plus d’informations
Philosophie de code
Vue d’ensemble
Modèles
API de la base de données
Conception des URLs
Système de template
Vues
Création d’un projet Django
Installation de Django
Création du projet en local
Qu’est ce qu’un projet Django
Création d’une application
Qu’est ce qu’une application
Standalone versus Coupled applications
Création des modèles
Qu’est ce qu’un model ?
Notre première application
Nos premiers models
Installation des models
Ce que nous voyons
Manipulations des models
Introduction aux URLs
Exemples
Activation de l’administration
Administration simple
Administration de nos application
Administration évoluée
Jour 2
3

Introduction aux vues


Utiliser les vue génériques
Configuration des urls
Les vues génériques wrappées
Les templates
Remarques
Philosophie des templates
Centralisation et héritage dans les templates
Technique à 3 niveaux
Création de managers
Remarque
Déploiement de l’application sur Apache
Fichiers statiques
Travaux pratiques
Jour 1

Introduction à Django
Django est un framework web écrit en Python, il était au départ développé pour un environnement de revue de
presse électronique appartenant à World Online.
Puis en Juillet 2005 il a été abstrait et publié comme framework web libre. Cet héritage est apparent dans
l’ensemble du paquetage : dans la documentation, dans l’interface d’admin, et dans la bibliothèque standard, par
exemple les types de champs gérés (ex: SlugField).
Django inclut tous les composants nécessaires au développement de n’importe quelle application web de base :

• Correspondance objet-relationnel pour la base de données (ORM).


• Un système de squelette séparant le code Python du code HTML (Templates).

Django n’utilise pas de serveur d’application tierce partie comme CherryPy. Il fournit par contre un script
gestionnaire qui démarre un serveur de developpement simple. Il s’appuie cependant sur un serveur web avec
mod_python ou FastCGI pour le déploiement en production.

Ses forces
• Mapping relationel objet, grande API, efficace, remarquée par Guido van Rosum.
• Systeme de cache.
• Backoffice généré.
• Design des URL.
• Système de templates simple, complet et extensible.
• Modules de contributions étendant les fonctionalitées.
• Documentation complète.
• Communautée active.
• Facilité d’apprentissage.
• Découpage intelligent des projets.
• Internationalisation.
• Extensibilitée.
• Rapidité de dévelopement.
• Support de MySQL, PostGres, SQLite...
• Outils d’administration de bases de données.

4
5

• Compatibilité WSGI.

• Philosophie DRY.

• Robuste.

Plus d’informations
• DjangoProject

• Django-fr

Philosophie de code

Vue d’ensemble
Couplage faible Les différentes couches du framework ne doivent pas se connaître les unes les autres à moins
que cela soit absolument nécessaire.

Moins de code Les applications Django doivent utiliser aussi peu de code que possible; elles doivent rester
agiles. Django doit permettre de profiter pleinement des possibilités dynamiques de Python, tel que
l’introspection.

Développement rapide L’intérêt d’un framework du 21ème siècle est de rendre rapide les tâches fastidieuses
du développement Web. Django doit donc permettre un développement Web plus rapide.

Ne vous répétez pas (Don’t Repeat Yourself) Chaque concept/portion de données distincts doivent
résider en un, et un seul, endroit. La redondance est mal. La normalisation est bien.

Explicite est meilleur qu’implicite Ceci est un principe au coeur même de Python, qui veut dire que Django
ne doit pas faire de choses trop magiques. La magie ne devrait pas apparaître tant qu’il n’y a pas de raison
valable pour cela. La magie vaut la peine d’être employée seulement si elle amène un grand confort, inac-
cessible d’une autre manière, et si elle n’est pas implémentée de manière à rendre confus les développeurs
qui essayent d’apprendre à utiliser la fonctionnalité.

Cohérence Le framework devrait être cohérent à tous niveaux. La cohérence s’applique à tout élément depuis
le bas niveau jusqu’au haut niveau.

Modèles
Inclure toute la logique appropriée Les modèles doivent encapsuler chaque aspect d’un objet, selon le de-
sign pattern Active Record <http://en.wikipedia.org/wiki/Active_record_pattern>_ de Martin Fowler. Les
logiques de plus haut niveau doivent aussi être inclues dans les modèles si possible.
6

API de la base de données


Efficacité SQL Elle doit exécuter des requêtes SQL le moins souvent possible, et optimiser les requêtes en
interne.

Syntaxe succinte mais puissante L’API de base de données doit autoriser de riches et consistantes re-
quêtes dans un minimum de syntaxe possible. Elle ne doit pas s’appuyer sur l’import d’autres modules
ou d’objets d’aide à la mise en forme. Les jointures devraient être réalisées automatiquement, en coulisse,
lorsque nécessaire.

Une option pour exécuter une requête SQL facilement L’API de base de données doit réaliser qu’elle
est un raccourci mais pas nécessairement un tout-en-un. Le framework doit donc rendre facile l’écriture
de SQL sur mesure -- des requêtes complètes, ou juste des clauses WHERE personnalisées en tant que
paramètres pour les appels à l’API.

Conception des URLs


Couplage faible Le système d’URL Django doit permettre aux URLs provenant de la même application d’être
différentes dans des contextes différents. Par exemple, un site peut mettre les articles à /articles/, alors
qu’un autre peut utiliser /nouvelles/.

Flexibilité infinie Les URLs doivent être aussi flexibles que possible. Toute conception d’URL imaginable
doit être permise.

Encourager les bonnes pratiques Le framework devrait faire en sorte qu’il soit facile (ou plus facile) pour
un développeur de concevoir de jolies URLs que des moches. Les extensions de fichier dans les URLs des
pages Web devraient être évités.

URLs permanentes Techniquement, foo.com/bar et foo.com/bar/ sont deux URLs différentes, et les robots
des moteurs de recherche (et quelques outils d’analyse du trafic) pourraient les traiter de manière séparées.
Django doit donc faire un effort pour “normaliser” les URLs afin ne pas permettre la confusion aux robots
des moteurs de recherche.

Système de template
Séparer la logique de la présentation Nous voyons un système de template comme un outil contrôlant la
présentation et la logique relative à la présentation -- et c’est tout. Le système de template ne doit pas
supporter de fonctionnalités qui vont au delà de ces principes de base.

Décourager la redondance L’héritage au sein des templates, permet de se passer de la duplication de cer-
tains éléments du contenu, tel le footer ou le header.

Etre dissocié du HTML Le système de template ne doit pas être conçu pour seulement produire du HTML.
Il doit être également bon à générer d’autres formats basés sur du texte, ou juste du texte.

Sûreté et sécurité Le système de template, nativement, devrait interdire l’inclusion de code malicieux -- tel
que des commandes supprimant les données en base.

Extensibilité Le système de template doit prendre en compte le fait que les auteurs de templates de niveau
avancé peuvent vouloir étendre cette technologie. C’est le concept derrière les tags et les filtres de template
sur mesure.
7

Vues
Simplicité L’écriture d’une vue doit être aussi simple que d’écrire une fonction Python. Les développeurs ne
doivent pas avoir besoin d’instancier une classe quand une fonction suffit.
Couplage faible Une vue ne doit pas se soucier du système de template que le développeur utilise -- ou même
si un système de template est utilisé ou non.
Différencier GET et POST GET et POST sont méthodes HTTP distinctss; les développeurs doivent ex-
plicitement utiliser l’un ou l’autre. Le framework doit facilement distinguer les données GET et POST.

Création d’un projet Django

Installation de Django
Pour commencer à utiliser Django, il est nécessaire de le télécharger et de l’installer. Nous allons nous baser sur
la dernière version stable publiée, qui est la 1.3.
Nous allons aussi utiliser virtualenv pour cloisonner notre système et éviter de l’impacter avec les différents
modules Python que nous allons utiliser.
Dans un terminal exécutons ces commandes :

$ virtualenv --no-site-packages mon_premier_projet


$ cd mon_premier_projet
$ source ./bin/activate
$ wget http://www.djangoproject.com/download/1.2.3/tarball/
$ tar -xvzf Django-1.2.3.tar.gz
$ cd Django-1.2.3
$ sudo python setup.py install

Création du projet en local


Maintenant que Django est installé, il est nécessaire de créer un répertoire monprojet qui sera un module Python
contenant tout le code de notre projet. Dans le répertoire actuel, exécutez la commande suivante

$ django-admin.py startproject monprojet

La structure de votre projet est désormais créé.

Qu’est ce qu’un projet Django


Au final qu’est ce qu’un projet Django ?
Si nous regardons le contenu du répertoire de notre projet, nous y retrouvons plusieurs choses :

__init__.py Ce fichier permet de dire à l’interpreteur Python que ce répertoire est un module Python. C’est
la norme.
manage.py Script Python reprenant les fonctionnalités de django-admin.py et qui servira aux tâches
d’administration de notre projet.
8

settings.py Ce fichier va contenir toute la configuration de notre projet. Il sert de point d’entrée à notre
projet. Ecrit en python, ce fichier de configuration est très souple à manipuler.
urls.py Comme son nom l’indique, ce fichier contiendra les urls associées à notre projet. Il est le squelette
du projet, faisant la liaison entre le code et les urls.

Au final nous pouvons donc dire qu’un projet Django est un module Python permettant l’administration et le
controle des différents composants intervenant dans le projet. Composants appelés Applications.

Création d’une application


Un projet étant constitué d’applications, Django fournit une commande pour créer rapidement la structure d’une
application au sein de notre projet, grâce à cette commande :

$ python manage.py startapp monapplication

On remarque que nous utilisons désormais le script manage.py, mais cette action est aussi valable grâce au script
django-admin.py.

Qu’est ce qu’une application


Une application est aussi un simple module Python. La meilleure preuve est de regarder le contenu du répertoire
monapplication. Les fichiers suivants sont présents :

__init__.py Ceci est le fichier qui prouve que le répertoire est un module Python, car sa présence l’indique
à l’interpréteur.
models.py Fichier Python qui contiendra les classes relatives aux models de notre l’application. Utiliser
ce fichier pour écrire ses models est la norme. Une bonne partie de la logique de notre application se
retrouvera dans ce fichier.
views.py Idem que pour models.py sauf qu’ici seront écrites les vues de l’application.

Une application Django est donc un simple module Python définissant un ensemble de fonctions et de classes,
qui seront utlisées au sein de notre projet.

Standalone versus Coupled applications


Il est important de savoir qu’il existe 2 manières de développer une application :

Coupled Une application dite Coupled est typiquement une application créée par la commande startapp au sein
de notre projet. Elle va lier l’application avec notre projet, ce qui aura l’inconvénient de devoir spécifier
précisement les chemins d’importation de l’application et d’en limiter grandement la réutilisabilitée.
Dans le cas d’un développement spécifique, ceci ne pose pas de problèmes, mais il n’est pas recommandé
de procéder ainsi.
Standalone Une application dite Standalone est une application indépendante du projet, qui peut résider
n’importe où du moment qu’elle est accessible par le PYTHONPATH. Dans le cas d’une application réutil-
isable et/ou distribuée, il est nécessaire de procéder ainsi.
Nous utiliserons cette méthode tout au long des travaux pratiques.
9

Création des modèles

Qu’est ce qu’un model ?


Un model est une classe dans Django servant à intéragir avec une base de données. Il doit contenir toutes les
propriétés et méthodes de notre objet représenté. Un model pouvant avoir des relations avec d’autres models, ces
relations devront êtres aussi décrites.
Les models serviront de structure à notre application, et en définiront une bonne partie de la logique.
C’est pour cette raison qu’il est nécessaire de commencer nos applications par une conception solide de nos
models.

Notre première application


Pour se baser sur un exemple concret, nous allons créer une application de répertoire téléphonique.
Dans votre répertoire de developpement tapez les commandes suivantes :

$ mkdir repertoire_telephonique
$ touch repertoire_telephonique/__init__.py
$ touch repertoire_telephonique/models.py

Etant donnée que cette application sera Standalone il est nécessaire qu’elle soit accessible grâce à la variable
d’environnement PYTHONPATH.
Pour cela, vous pouvez créer par exemple votre application dans un répertoire indiqué par PYTHONPATH

$ echo $PYTHON_PATH

Vous pouvez aussi modifier votre variable d’environnement en rajoutant votre répertoire de développement au
PYTHONPATH.
Ou bien créer un lien symbolique depuis un répertoire accessible vers votre module.

Nos premiers models


Nous devons maintenant construire nos models qui vont définir donc la logique de notre application. Notre
application sera constituée de 2 models, l’un représentant un Contact et un autre représentant ses numéros de
téléphones.
Editons le fichier repertoire_telephonique/models.py pour qu’il ressemble à cela :

from django.db import models

class Contact(models.Model):

first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)

def __unicode__(self):
return ’%s %s’ % (self.first_name, self.last_name)

class Phone(models.Model)
10

PHONE_CHOICES = ((’pro’, ’Professionel’),


(’mobile’, ’Mobile’),
(’fixe’, ’Fixe’))

contact = models.ForeignKey(Contact, null=True, blank=True)


type = models.CharField(max_length=10, choices=PHONE_CHOICES)
value = models.CharField(max_length=20)

def __unicode__(self):
return ’%s %s : %s’ % (self.contact, self.type, self.value)

Installation des models


Maintenant que nous possédons, nos propres models, il est nécessaire de les installer pour commencer à les
utiliser.
Installer les models d’une application, revient à installer l’application.
Pour cela, il faut éditer les ficher settings.py de notre projet, et d’y rajouter ’repertoire_telephonique’, dans
la section INSTALLED_APPS.
Maintenant nous allons établir une synchronisation entre les models et notre base de donnée. Cette synchronisa-
tion servira à créer les tables SQL décrites par vos models.

$ python manage.py syncdb

Ce que nous voyons


Les models écrits vont servir d’interface avec la base de donnée. Les attributs de classe définis au sein du model
serviront de colonnes et en définieront le type. Ce sont les Fields.
Il existe des Fields pour à peu prêt chaque cas, il est même possible de créer ses propres Fields.

Manipulations des models


Il possible désormais d’utiliser nos models pour intérargir avec la base de données :

$ python manage.py dbshell

>>> from repertoire_telephonique.models import Contact, Phone


>>> Contact.objects.get_or_create(first_name=’Julien’, last_name=’Fantomas’)
>>> Contact.objects.all().count()
... 1

Introduction aux URLs


Le système d’URLs au sein de Django est une des fonctionnalités les plus intéressantes de Django pour ces
raisons suivantes :
11

Motif Les URLs sont constituées de motifs permettants la variation et l’écriture de n’importe qu’elle URL et le
passage de paramètres de manière élégante.

Rapidité Les URLs sont compilées une seule fois, au démarrage du serveur pour un gain de temps.

Couplage faible Les URLs sont décentralisées, et permettent l’association entre le motif de l’URL et une vue.

Il est bon de savoir que les URLs peuvent être nommées, pour un soucis de claireté et aussi pour eviter d’avoir
un couplage fort au sein de vos templates et vues. Nous verrons cela en détail plus tard.

Exemples
Voici un exemple simple de vue en liste et detaillée :

urlpatterns = patterns(’django.views.generic.list_detail’,
url(r’^$’, ’object_list’,
name=’my_object_list’),
url(r’^(?P<object_id>\d+)/$’, ’object_detail’,
name=’my_object_detail’),
)

Ce qui donnera à l’utilisation dans votre navigateur les URLs suivantes :

• http://example.com/

• http://example.com/42/

Activation de l’administration
Une autre des fonctionnalités les plus utiles au sein de Django, et qui a permis au framework de se diffuser
rapidement, est sans conteste l’application d’administration.
L’application d’administration est un module Python fournis de base dans la distrbution de Django, se situant
dans le répertoire contrib de notre module Django. Nous pouvons voir que dans ce dossier d’autres applications
sont fournies avec les sources de Django.

Administration simple
Une des premières choses à effectuer est d’installer le module d’administration.
Pour cela dans le fichier settings.py de notre projet ajoutons ’django.contrib.admin’ à l’intérieur de la
section INSTALLED_APPS.
Pour continuer l’installation il est nécessaire d’associer une URL aux vues du module d’administration.
Le fichier urls.py situé dans notre projet contient déjà un exemple d’URLs pour accèder aux vues de
l’administration, mais il est commenté. Décommentons les lignes suivantes, pour avoir ceci :

from django.contrib import admin


admin.autodiscover()

url(r’^admin/’, include(admin.site.urls)),
12

Ensuite exécutons la commande suivante, pour synchroniser les models contenus dans l’application admin afin
d’en assurer son fonctionnement.

$ python manage.py syncdb

Désormais, si on lance le serveur de développement de Django, par la présente commande,

$ python manage.py runserver

on peut accéder à l’interface d’administration grâce à cette url : http://localhost:8000/admin


Une fois identifié vous pouvez voir une liste des différentes applications installées sur le serveur et qui sont
administrables.
Par contre, nous ne voyons pas notre application au sein de l’administration, ce qui est plutot dommage, donc
nous allons remédier à cela.

Administration de nos application


Pour activer nos applications aux seins du module d’administration c’est très simple, il suffit simplement
d’enregistrer nos models dans le site d’administration.
Pour cela nous allons créer un module admin.py au sein de notre application de répertoire téléphonique.

$ cd repertoire_telephonique/
$ touch admin.py

Maintenant editons le pour qu’il ressemble à cela :

from django.contrib import admin

from repertoire_telephonique.models import Contact


from repertoire_telephonique.models import Phone

admin.site.register(Phone)
admin.site.register(Contact)

Désormais si on relance le serveur de développement, et que l’on recharge la page d’accueil de l’administration,
nous y voyons apparaitre notre application avec ses tables prêtes à être administrées.
Le résultat est plutôt basique, mais il est possible d’aller plus loin dans la configuration de l’administration de
nos models.

Administration évoluée
Pour atteindre un résultat où les vues d’administration sont efficaces et facile à utiliser, il est souvent nécessaire
de les configurer.
Il nous faut donc créer différentes classes définissants le comportenant de chacuns de nos models dans
l’administration.
Ajoutons ce bout de code dans notre fichier admin.py :
13

class ContactAdmin(admin.ModelAdmin):
list_display = (’first_name’, ’last_name’)

class PhoneAdmin(admin.ModelAdmin):
list_display = (’contact’, ’type’, ’value’)

admin.site.register(Phone, PhoneAdmin)
admin.site.register(Contact, ContactAdmin)

Nous venons juste modifier l’affichage de la vue en liste de l’admin, mais elle paraît déjà plus utile.
Désormais si on regarde la documentation du module d’administration nous voyons qu’il existe pas mal de
possibilités pour personaliser l’interface d’administration.
Essayons un peu.
Jour 2
Pour illustrer la suite de mes propos, nous allons avoir besoin de créer une application plus conséquente, car le
répertoire téléphonique est déjà complet grâce au module d’administration qui remplit toutes les fonctionnalités
attendues d’un répertoire téléphonique.
Nous allons donc créer maintenant un mini-moteur de publication de nouvelles qui sera accesible sur le frontal
du site.
Cette application portera le nom de npublisher.
Nous nous imposerons cette liste de fonctionnalités :

• Gestion des catégories.


• Gestion des auteurs.
• Gestion de la publication, visible ou non.
• Facilitées de publication et de référencement.

Le reste des données du model est libre.


Créons donc les models, et activons ensuite l’interface d’administration.
Une fois que nous aurons une interface d’administration efficace, nous allons nous attaquer au coté front de
l’application.

Introduction aux vues


Une vue dans Django, est une fonction (ou bien une méthode si on utilise les nouvelles vues génériques), qui
recevra en premier argument, un objet représentant la requete HTTP envoyée par le client.
Une vue peut recevoir plusieurs paramètres, pour en assurer la réutilisation.
Une vue doit toujours retourner une réponse HTTP.
Les vues répresentent par exemple une vue en liste d’un model, ou sa vue détaillée.
Elles peuvent aussi très bien réprésenter le résultat d’une recherche, ou des formulaires d’éditions, des fichiers à
télécharger, tout ce qui est permis par le protocole HTTP.

Utiliser les vue génériques


Ecrire des vues avec l’habitude devient une tâche longue et répétive.
Par exemple, il est souvent nécessaire d’écrire la vue en liste puis, la vue détaillée d’un model précis.
Heureusement Django peut palier à ce problème grâce à une collection de vues génériques incorporée dans sa
distribution.
Ces vues permettent dans la majorité des cas de ne pas écrire de code Python (ou très peu), ce qui a un avantage
certain.

14
15

Configuration des urls


Pour utiliser les vues génériques, tout va se passer aux niveaux des URLs.
Dans le répertoire de notre application npublisher nous allons donc créer un fichier nommé urls.py contenant
ce bout de code :

"""Urls of npublisher"""
from django.conf.urls.defaults import *

from npublisher.models import Entry

entry_conf = {’queryset’: Entry.objects.all()}

urlpatterns = patterns(’django.views.generic.list_detail’,
url(r’^$’, ’object_list’,
entry_conf, ’npublisher_entry_list’),
url(r’^(?P<slug>[-\w]+)/$’, ’object_detail’,
entry_conf, ’npublisher_entry_detail’),
)

A partir de là plusieurs choses sont à noter :

• Ce fichier d’URLs peut être inclus dans le fichier d’URLs de votre projet, grâce à la fonction include,
exemple :
url(r’^informations/’, include(’npublisher.urls’)),
• Désormais grâce au nommage des URLs, il est possible d’avoir un couplage faible au niveau du model,
tout en lui définissant une URL absolue, utile elle aussi pour la notion de couplage faible.
Seul le fichiers urls.py de votre projet sera maître de chaque URLs utilisées dans votre projet, grâce à
un mécanisme d’acquisition inverse.
Utilisons cette possibilitée sur notre model Entry et ajoutont cette méthode :
class Entry(models.Model):
...
@models.permalink
def get_absolute_url(self):
return (’npublisher_entry_detail’, (), {’slug’: self.slug})
• Un seul fichier, peu de code, des URLs réutilisables.
• queryset est le seul argument obligatoire pour nos vues, il défini de manière dynamique sur quelles in-
stances de notre model Entry la vue peut agir.

Les vues génériques wrappées


Il peut arriver des cas, où les vues génériques ne répondent pas tout à fait à notre besoin.
Par exemple si nous voulons faire une vue filtrant les entrées par catégories, nous retournons toujours des entrées,
mais la queryset ne sera pas bonne car la notion de filtre de ne pourra pas être appliquée.
Dans ce cas il est possible d’écrire une vue générique wrappée ou transformée.
Nous allons donc créer un fichier views.py dans le répertoire de notre application. Il devrait ressembler à cela
:
16

"""Views of npublisher"""
from django.shortcuts import get_object_or_404
from django.views.generic.list_detail import object_list

from npublisher.models import Category

def category_view_entry(request, slug):


"""Return the view for entry of a category"""
category = get_object_or_404(Category, slug=slug)
return object_list(request, queryset=category.entry_set.all(),
extra_context={’category’: category})

Cette vue va retrouver la catégorie dont le slug est passé en paramètre, ce qui va nous permettre de générer une
queryset filtrant les entrées de cette catégorie.
Ensuite nous retournons la vue générique object_list correctement configurée avec notre queryset et la
variable category dans le context, pour l’afficher dans notre template plus tard.
Utiliser le système de vue générique permet de s’affranchir de beaucoup de lignes de code redondantes et de
rester constant au sein de notre application.
Cette vue doit maintenant etre associée à une URL, donc dans notre fichier urls.py de l’application npublisher
nous rajoutons ceci :

urlpatterns += patterns(’’,
url(r’^category/(?P<slug>[-\w]+)/$’, ’npublisher.views.categ
name=’npublisher_category_view_entry’),
)

Comme nous le voyons il est possible d’additionner des URLs. Ceci est une possibilité des instances de type
patterns.

Les templates
Actuellement nous avons le code, c’est à dire la logique de l’application, mais pas de rendu.
Si nous testons les URLs que nous avons créées, elles retournent une erreur spécifiant que le template
npublisher/entry_list.html n’existe pas.
Le nom du template manquant est défini par le comportement des vues génériques, qui vont prendre le nom de
l’application suivis d’un ’/’ puis du nom du model utilisé avec pour finir _detail.html ou _list.html en fonction de
la vue appelée.
Mais il est possible de spécifier un autre nom de template au besoin.
Nous allons donc créer les templates qui manquent.
Au sein de notre application, nous allons créer un répertoire nommé templates, puis créer un sous répertoire
nommé lui npublisher.
Une fois dans le répertoire npublisher du dossier templates, nous allons créer les templates manquant.

$ cd npublisher
$ mkdir -p templates/npublisher
$ cd templates/npublisher
$ touch entry_list.html
$ touch entry_detail.html
17

Si nous actualisons notre navigateur, l’erreur n’apparaît plus, mais en fait rien n’apparait.
Ceci est normal car pour l’instant nos templates sont vides.

Remarques
• Django possède plusieurs systèmes d’acquisition des templates.
Par défaut, le premier étant celui qui va regarder dans la liste de dossiers définis dans la section
TEMPLATE_DIRS de votre fichier settings.py.
Un autre mécanisme va vérifier dans chaques applications installées si un dossier nommé templates
existe pour l’inclure dans la recherche de templates. C’est ici la technique utiliser.

• Grâce à ces différentes techniques d’acquisition, il est possible de modifier le rendu d’une application par
défaut, en dupliquant le template visé pour le modifier et le mettre dans un chemin d’acquistion prioritaire.

• Il est donc aisé de fournir un jeu de templates par défaut à une application réutilisable, tout en permettant
un haut degré de personalisation.

Philosophie des templates


Un template, sert juste à mettre en forme des données.
C’est pourquoi le système de template est tout aussi bien capable de produire du HTML, du CSV ou en encore
du PDF si on le veut.
Les templates ne doivent pas incorporer trop de logiques, sauf celles de la présentation, le reste doit être délégué
aux vues ou aux models en eux meme.
Maintenant réalisons nos templates.

Centralisation et héritage dans les templates


Le système de templating dans Django est assez puissant pour permettre l’héritage entre templates. Cette fonc-
tionnalitée évite la redondance de certains éléments présent entre les différents templates.
Dans le cas d’un site internet, c’est éléments, seront par exemple les métas de publication, la navigation, le footer,
etc. Inutile de copier coller, ou d’inclure, il suffit d’hériter.

Technique à 3 niveaux
Il est possible de faire à peu prêt ce que l’on veut avec le système de template, mais il existe une technique
d’organisation qui allie personalisation et robustesse, nommée technique à 3 niveaux.
Dans la section TEMPLATE_DIRS du fichier settings.py de votre projet, nous allons spécifier un répertoire
d’acquisition.
Il est d’usage de créer un répertoire nommé templates au sein même de notre projet, et de spécifier celui ci
en priorité.
Dans ce dossier nous allons ensuite créer un fichier nommé base.html, celui-ci contiendra le squelette HTML
de notre site web.
Autours des zones dont le contenu changera, nous allons poser des tags block. Ces tag block sont souvent les
mêmes, exemple :
18

• la zone de CSS
• la zone de Javascript
• la balise title
• la zone de contenu
• la navigation

Exemple :

<title>Mon site {% block title%}{% endblock %}</title>

Ensuite nous allons créer dans le dossier templates/npublisher de notre application un fichier nommé
aussi base.html ce fichier héritera de notre fichier base.html créer précèdement.
Ensuite il pourra surcharger les blocks hérités de son parent.

{% extends "base.html" %}

{% block title %}NPublisher{% endblock %}

Désormais dans chacun des templates de notre application, nous hériterons de application/base.html
qui nous fournira une structure de template déjà configurée. Par exemple dans entry_list.html :

{% extends "npublisher/base.html" %}

{% block title %}{{ block.super }} Entrées{% endblock %}

Il suffit ensuite de définir la zone de contenu à afficher dans le block représentant le contenu dans le template
principal.
Si une modification doit etre apportée sur tout le module au niveau du design, il suffit juste de modifier le fichier
base.html de l’application.

Création de managers
Maintenant que nous avons nos vues, nous remarquons un problème, même les entrées marquées du champs
visible à False sont affichées dans la vue en liste.
Une solution serait de modifier la queryset passée en paramètre dans les vues génériques, mais cela ne serait pas
très pratique dans l’utilisation, car cela nous fait trainer du code qui devrait faire partie de la logique de l’objet.
Une autre solution serait de modifier les managers de notre model Entry.
Chaque model possède un manager par défaut, nommé objects par défaut, mais il possible d’en ajouter d’autres
pour répondre à différents besoins.
Nous allons donc créer un manager pour notre model Entry, qui permettra de retrouver rapidement les entrées
publiées et seulement celles-là.
Dans notre fichier models.py, nous allons donc rajouter cette classe, pour que cela fonctionne.

class EntryPublishedManager(models.Manager):
"""Manager to retrieve published entries"""

def get_query_set(self):
return super(EntryPublishedManager, self).get_query_set().filter(visible=Tr
19

Cette classe hérite de models.Manager, et surcharge le comportement de la méthode get_query_set qui


définit le comment un model retrouve ses instances en base de données.
Dans notre classe Entry il faut désormais rajouter ces lignes :

objects = models.Manager()
published = EntryPublishedManager()

Et maintenant dans le fichier urls.py de notre application, il faut changer le dictionnaire entry_conf par
ceci :

entry_conf = {’queryset’: Entry.published.all()}

Désormais seules les entrées publiées seront retournées par la vue.

Remarque
Nous voyons que nous avons rajouté à la première ligne de notre model, l’attribut objects. Ce n’est pas
obligatoire, mais il est nécessaire de l’utiliser pour assurer une compatibilité avec les autres applications de notre
site.
Pourquoi le déclarer alors ?

Car dans le fonctionnement des models, la première classe hérité de models.Manager, va devenir
le manager par défaut de notre model.
C’est un comportement à prendre en compte lors de l’ajout d’un nouveau manager.

Déploiement de l’application sur Apache


Le serveur de développement n’est pas une bonne initiative pour déployer son application.
Comme son nom l’indique il sert au développement. En effet il n’est pas conçu pour servir à grande échelle les
fichiers, sans compter au niveau de la sécurité les lacunes existantes.
Par contre Apache2 ou NGinx remplissent très bien ce rôle.
Nous allons voir le cas d’un déployement avec Apache et ModPython.
Dans le répertoire sites-available de notre installations d’Apache2 nous allons écrire une nouvelle con-
figuration.

<VirtualHost *:80>
ServerName monserveur.domain.com

DocumentRoot /repertoire/de/votre/projet

<Location "/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE projet.settings
PythonDebug On
PythonPath "[’repertoire/de/votre/projet’, ’repertoire/de/votre/projet/appl
</Location>
</VirtualHost>

Avec ceci, votre projet est prêt à être en production.


20

Fichiers statiques
Il reste cependant une chose à régler, comment servir les fichiers statiques de votre projet ?
Django peut très bien faire cela, mais une fois de plus cette solution n’est pas adaptée, ni optimisée, car Django
sert à executer du code Python et non à servir des fichiers.
Donc pour régler ce problème nous allons modifier notre configuration Apache pour que ce soit lui qui serve les
fichiers statiques.
Dans la section VirtualHost de votre configuration, il suffit de rajouter ceci pour chaques répertoires à servir.

Alias /css /repertoire/de/fichiers/static/css


<Location "/css">
SetHandler None
</Location>

Le tour est joué.

Travaux pratiques
Vous allez maintenant créer une nouvelle application, réutilisable.
Le but de cette application sera de pouvoir créer et publier des galleries de photos sur notre projet web.

You might also like