Tout savoir sur Django

Le framework web pour les perfectionnistes pressés

Par David Larlet, développeur heureux.



Présentation accessible en ligne sur : http://larlet.fr/conferences/django/

Présentation de l'auteur

David Larlet, 25 ans, développeur web python

Quel est votre profil ?

Sondage

Le chef vous propose

(sous réserve d'approvisionnement hydra^W^alcoolisé)

Pourquoi un framework web ? Pourquoi Django ?

Objectifs et intérêts de Django

Bref historique

Objectifs et intérêts de Django

Configuration requise

Objectifs et intérêts de Django

Philosophie

Objectifs et intérêts de Django

Utilisateurs actuels

Objectifs et intérêts de Django

MTV : Model Template View

Mécanisme général

Attention le C du MVC correspond ici au V, et le V au T !

Du navigateur aux URL

Itinéraire d'une requête

Utilisez Firefox.

Des URL aux vues

Itinéraire d'une requête

Via des liens directs :

urlpatterns = patterns('',
    (r'^archives/$', archives),
)

ou basé sur des expressions régulières :

urlpatterns += patterns('',
    (r'^archives/(?P<year>\d{4})/$', archives_year),
)

Interactions vues/modèles

Itinéraire d'une requête

Via un ORM simple

from myproject.blog.models import Post

def archives(request):
    posts = Post.objects.all()

permettant aussi de faire des choses compliquées

posts = Post.objects.filter(is_online=True).distinct()

ou même du SQL selon les besoins.

Des vues aux templates

Itinéraire d'une requête

Passage d'un dictionnaire à un template

from django.shortcuts import render_to_response
from myproject.blog.models import Post

def index(request):
    latest_posts = Post.objects.all()[:5]
    return render_to_response('blog/index.html',
        {'latest_posts': latest_posts})

Les objets QuerySet sont des itérateurs

Affichage des templates

Itinéraire d'une requête

Un langage de template simple :

<ul>
{% for post in latest_posts %}
    <li>{{ post.title }}</li>
{% endfor %}
</ul>

Il suffit de différencier les {% blocs %} des {{ variables }}

LE schéma final pour tout comprendre

Itinéraire d'une requête

Schéma d'une requête avec Django

Spécifications d'un blog

Exemple concret

Modèle de données (models.py)

Exemple concret

En restant extrêmement basique...

class Post(models.Model):
    title = models.CharField(maxlength=250,)
    slug = models.SlugField(prepopulate_from=('title',))
    content = models.TextField()
    pub_date = models.DateTimeField()
    tags = models.ManyToManyField(Tag)

    def get_absolute_url(self):
        return ('myproject.blog.views.item', str(self.id))
    get_absolute_url = permalink(get_absolute_url)

Il est bien entendu possible d'ajouter d'autres fonctions

Interface d'administration auto-générée

Exemple concret

Capture de l'interface d'administration de Django

Interface d'administration auto-générée et shell

Exemple concret

En ajoutant une seule ligne au modèle :

class Post(models.Model):
    [...]
    class Admin:
        pass

Possibilité d'utiliser les modèles via un shell :

$ python manage.py shell
>>> from myproject.blog.models import Post
>>> Post.objects.all()
[<Post: Les JFP une réussite !>]

Accès aux ressources (urls.py)

Exemple concret

On distingue les ressources de l'agrégation :

urlpatterns = patterns('',
    (r'^/blog/(?P<year>\d{4})/(?P<month>\d{2})/ »
        (?P<day>\w{1,2})/(?P<slug>\w+)/$', blog_post),

    (r'^/blog/$', post_list),
)

Il est possible d'ajouter des archives par date, etc

Vues et traitement (views.py)

Exemple concret

On distingue les ressources de l'agrégation :

def blog_post(request, year, month, day, slug):
    post = get_object_or_404(Post, slug = slug)
    return render_to_response('blog/item.html', {'post': post})

def post_list(request):
    latest_posts = Post.objects.all().order_by('pub_date')[:10]
    return render_to_response('blog/index.html',
        {'latest_posts': latest_posts})

Il est bien entendu possible d'ajouter d'autres fonctions

Utilisation des templates (blog/index.html)

Exemple concret

Affichage de la liste des billets de blog :

<div>
{% for post in latest_posts %}
    <h2>
        <a href="{{ post.get_absolute_url }}">
            {{ post.title }}
        </a>
    </h2>
    {{ post.content }}
    <p>{{ post.pub_date }}</p>
{% endfor %}
</div>

Flux RSS

Exemple concret

Création d'une classe, association d'une URL

class LatestPosts(Feed):
    title = "Twitter n'a qu'a bien se tenir"
    link = "/blog/"
    description = "Ma vie, minute par minute."

    def items(self):
        return Post.objects.order_by('-pub_date')[:5]

urlpatterns = patterns('',
    (r'^feeds/(?P<url>.*)/$',
        'django.contrib.syndication.views.feed',
        {'feed_dict': { 'blog': LatestPosts }}))

Vues génériques

Raccourcis intéressants

L'objectif est de gagner du temps :

Les paramètres par défaut suffisent dans la plupart des cas.

Héritage des templates

Raccourcis intéressants

Vous pouvez étendre un template de base :

{% extends "base.html" %}
{% block content %}
<p>
    Le contenu de ce paragraphe va s'afficher dans la
    partie content du template de base, il est possible
    d'avoir plusieurs niveau d'héritage et donc
    plusieurs templates de base.
</p>
{% endblock %}

Gain en généricité et donc en rapidité de développement.

Templatetags

Raccourcis intéressants

Permettent la récupération, le traitement ou l'affichage de données

{{ post.content|markdown }}
<p>Le {{ post.pub_date|date:"j F Y"|lower }}</p>

Il est possible de créer sa propre bibliothèque.

Les morceaux de codes redondants peuvent être factorisés dans des inclusion_tag dynamiques.

Internationalisation (I18N)

Raccourcis intéressants

Utilisation de gettext possible à différents niveaux :

Traitement comme des locales classiques.

Manager

Django avancé

class PostManager(models.Manager):
    def get_query_set(self):
        qs = super(PostManager, self).get_query_set()
        return qs.filter(is_online=True)

class Post(models.Model):
    [...]
    objects = models.Manager()
    published = PostManager()

Permet de distinguer Post.objects.all() et Post.published.all() lorsque l'on manipule les objets.

Signals

Django avancé

Envoi d'un mail à chaque nouveau billet :

def rss_by_mail(sender, instance):
    [...]
    send_mass_mail([...])

dispatcher.connect(rss_by_mail,
    signal=signals.post_save, sender=Post)

Les signals permettent d'effectuer des tâches de routine au niveau des modèles. Il est par exemple possible de mettre en place une historisation grâce à ce système.

Middleware

Django avancé

Exemple pour REST :

class HttpMethodsMiddleware(object):
    def process_request(self, request):
        if request.POST and 'verb' in request.POST:
            if request.POST['verb'] in ['PUT', 'DELETE']:
                request.method = request.POST['verb']
        return None

Récupération du verbe HTTP dans le champ caché 'verb' de tous les formulaires qui sont POSTés. On peut ensuite gérer les actions associées dans les vues.

Testing

Django avancé

Implémentation des doctests et des unittests

c = Client()
c.get('/blog/')
c.post('/blog/comments/', {'name':'david', 'content':'lol'})

Contributions

Django avancé

De nombreuses autres applications sont disponibles :

Popularité

Pour aller plus loin...

Difficile à mesurer, mais :

Vers la 1.0 !

Pour aller plus loin...

Ressources

Pour aller plus loin...

Publicité : django-fr recherche des traducteurs :-).

Discussion

Pour aller plus loin...

Un vilain troll velu des montagne

Remerciements

Pour aller plus loin...

Et bien sûr tous les développeurs Django !