Applications Web

En tant que puissant langage de scripting adapté à la fois au prototypage rapide et à de plus gros projets, Python est largement utilisé dans le développement d’applications web.

Contexte

WSGI

Le Web Server Gateway Interface (ou “WSGI” pour faire court) est une interface standard entre les serveurs Web et les frameworks web Python. En normalisant le comportement et la communication entre les serveurs Web et les frameworks web Python, WSGI permet d’écrire du code web Python portable qui peut être déployé dans tout serveur Web conforme à WSGI. WSGI est documentée dans la PEP 3333.

Frameworks

D’une manière générale, un framework web se compose d’un ensemble de bibliothèques et un gestionnaire principal au sein duquel vous pouvez construire un code personnalisé pour implémenter une application Web (par exemple, un site web interactif). La plupart des frameworks web incluent des modèles et des utilitaires pour accomplir au moins ce qui suit:

Routing d’URL

Fait correspondre une requête HTTP entrante vers un bout de code Python particulier pour être invoqué

Objets Requête et Réponse

Encapsule l’information reçue ou expédiée au navigateur d’un utilisateur

Moteur de template

Permet la séparation du code Python implémentant la logique d’une application de la sortie HTML (ou autre) qu’elle produit

Serveur web de développement

Exécute un serveur HTTP sur les machines de développement pour permettre un développement rapide; souvent recharge automatiquement le code côté serveur quand les fichiers sont mis à jour

Django

Django est un framework d’application web “tout en un”, et est un excellent choix pour la création de sites Web orientés contenu. En fournissant utilitaires et patterns par défaut, Django a pour but de permettre de construire rapidement des applications web complexes Web, reposant sur des base de données, tout en encourageant les bonnes pratiques dans le code écrit qui l’utilise.

Django a une communauté importante et active, et de nombreux modules pré-construits réutilisables qui peuvent être incorporés dans un nouveau projet tel quel, ou personnalisé pour répondre à vos besoins.

Il y a des conférences annuelles de Django aux États-Unis et en Europe.

La majorité des nouvelles applications web Python d’aujourd’hui sont construites avec Django.

Flask

Flask est un “microframework” pour Python, et est un excellent choix pour la construction de petites applications, d’APIs et des services Web.

Construire une application avec Flask est un peu comme l’écriture des modules standards de Python, sauf certaines fonctions ont des routes qui leur sont rattachées. C’est vraiment très beau.

Plutôt que de viser à fournir tout ce dont vous pourriez avoir besoin, Flask implémente les composants noyaux les plus couramment utilisés d’un framework web, comme le routage d’URL, les objets request et response et les templates.

Si vous utilisez Flask, c’est à vous de choisir d’autres composants pour votre application, le cas échéant. Par exemple, l’accès aux base de données ou la génération et la validation de formulaires ne sont pas des fonctions natives dans Flask.

C’est super, car de nombreuses applications Web ne nécessitent pas ces fonctionnalités. Pour celles qui en ont besoin, il y a de nombreuses extensions disponibles qui peuvent répondre à vos besoins. Ou, vous pouvez facilement utiliser toute bibliothèque dont vous voulez vous-même!

Flask est le choix par défaut pour toutes les applications web Python qui ne sont pas adaptées à Django.

Tornado

Tornado est un framework web asynchrone pour Python qui a sa propre boucle d’événements. Cela lui permet de supporter nativement les WebSockets, par exemple. Les applications Tornado bien écrites sont connues pour avoir d’excellentes performances.

Je ne recommande pas d’utiliser Tornado sauf si vous pensez que vous en avez besoin.

Pyramid

Pyramid est un framework très souple se concentrant fortement sur la modularité. Il est livré avec un petit nombre de bibliothèques (“toutes en unes”) intégrées, et encourage les utilisateurs à étendre ses fonctionnalités de base.

Pyramid n’a pas une grosse base d’utilisateurs, contrairement à Django et Flask. C’est un framework intelligent, mais pas un choix très populaire pour les nouvelles applications web Python de nos jours.

Serveurs web

Nginx

Nginx (prononcé “engine-x ”) est un serveur web et un reverse-proxy pour HTTP, SMTP et d’autres protocoles. Il est connu pour sa haute performance, la simplicité relative, et sa compatibilité avec de nombreux serveurs d’applications (comme les serveurs WSGI). Il inclut aussi des fonctionnalités pratiques comme le load-balancing, l’authentification basique, le streaming, et d’autres encore. Conçu pour servir des sites à forte charge, Nginx est progressivement en train de devenir populaire.

Serveurs WSGI

Les serveurs WSGI autonomes utilisent généralement moins de ressources que les serveurs web traditionnels et offrent les meilleures performances [3].

Gunicorn

Gunicorn (Green Unicorn) est un serveur de WSGI en pur-python utilisé pour servir des applications Python. Contrairement à d’autres serveurs web Python, il a une interface utilisateur réfléchie, et est extrêmement facile à utiliser et à configurer.

Gunicorn a des configurations par défaut saines et raisonnables. Cependant, certains autres serveurs, comme uWSGI, sont largement plus personnalisables, et par conséquent, sont beaucoup plus difficiles à utiliser efficacement.

Gunicorn est le choix recommandé pour de nouvelles applications Python web aujourd’hui.

Waitress

Waitress est un serveur de WSGI pur-python qui affirme avoir des “performances très acceptables”. Sa documentation est pas très détaillée, mais elle offre quelques fonctionnalités intéressantes que Gunicorn n’a pas (par exemple la mise en mémoire tampon de requête HTTP).

Waitress gagne en popularité au sein de la communauté de développement web Python.

uWSGI

uWSGI est une pile complète pour construire des services d’hébergement. En plus de la gestion des processus, la surveillance des processus, et d’autres fonctionnalités, uWSGI agit comme un serveur d’applications pour différents langages de programmation et protocoles - y compris Python et WSGI. uWSGI peut soit être exécuté comme un routeur Web autonome, ou être exécuté derrière un serveur web complet (comme Nginx ou Apache). Dans ce dernier cas, un serveur Web peut configurer uWSGI et le fonctionnement d’une application par dessus le protocole uwsgi. Le support d’un serveur Web uWSGI permet la configuration dynamique de Python, en passant des variables d’environnement et plus de réglages. Pour plus de détails, reportez-vous aux variables magiques uWSGI.

Je ne recommande pas d’utiliser uWSGI sauf si vous savez pourquoi vous en avez besoin.

Meilleures pratiques serveur

La majorité des applications auto-hébergées Python aujourd’hui est hébergée avec un serveur WSGI tels que Gunicorn, soit directement, soit derrière un serveur web léger tel que nginx.

Les serveurs WSGI servent les applications Python pendant que le serveur Web gère les tâches mieux adaptées pour lui comme la mise à disposition des fichiers statiques, les requêtes de routage, la protection DDoS, et l’authentification basique.

Hébergement

Un Platform-as-a-Service (PaaS) est un type d’infrastructure de “cloud computing” qui fait abstraction et gère l’infrastructure, le routage et le scaling des applications Web. Lorsque vous utilisez un PaaS, les développeurs d’applications peuvent se concentrer sur l’écriture du code de l’application plutôt que de se préoccuper des détails du déploiement.

Heroku

Heroku offre un soutien de première classe pour les applications Python 2,7–3,5

Heroku supporte tous les types d’applications Python Web, serveurs et frameworks. Les applications peuvent être développées sur Heroku gratuitement. Une fois que votre application est prête pour la production, vous pouvez passer votre application en formule Hobby ou Professional.

Heroku maintient des articles détaillés sur l’utilisation de Python avec Heroku, ainsi que des instructions pas à pas sur comment configurer votre première application.

Heroku est le PaaS recommandé pour le déploiement d’applications web Python aujourd’hui.

Gondor

Gondor est un PaaS spécialisé pour le déploiement d’applications Django et Pinax. Gondor recommande Django version 1.6 et prend en charge toutes les applications WSGI sur Python version 2.7. Gondor peut configurer automatiquement votre site Django si vous utilisez local_settings.py pour les informations de configuration spécifiques au site.

Gondor a un guide sur le déploiement de projets Django.

Gondor est géré par une petite entreprise et se concentre pour aider les entreprises à trouver le succès avec Python et Django.

Templating

La plupart des applications WSGI répondent à des requêtes HTTP pour servir du contenu en HTML ou d’autres langages de balisage. Au lieu de générer directement le contenu textuel depuis Python, le concept de séparation des problèmes nous conseille d’utiliser des templates. Un moteur de template gère un ensemble de fichiers de templates, avec un système de hiérarchie et d’inclusion pour éviter des répétitions inutiles, et est en charge du rendu (génération) du contenu proprement dit, remplissant le contenu statique des templates avec le contenu dynamique généré par l’application .

Comme les fichiers de template sont parfois écrits par des designers ou développeurs front-end, il peut être difficile de gérer une complexité croissante.

Quelques bonnes pratiques générales s’appliquent à la partie de l’application qui passe le contenu dynamique au moteur de template, et aux templates eux-mêmes

  • Les fichiers de template ne doivent passer que le contenu dynamique nécessaire pour faire le rendu du template. Évitez la tentation de passer du contenu supplémentaire “juste au cas où”: il est plus facile d’ajouter une variable manquante en cas de besoin que de supprimer une variable inutilisée plus tard.

  • Beaucoup de moteurs de template des déclarations complexes ou des affectations dans le template lui-même, et beaucoup autorisent qu’un peu de code Python soit évalué dans les templates. Cette facilité peut entraîner une augmentation incontrôlée de la complexité, et souvent rendre plus difficile de trouver les bugs.

  • Il est souvent nécessaire de mélanger les templates JavaScript avec des templates HTML. Une approche saine à cette conception est d’isoler les parties où le template HTML passe un contenu variable au code JavaScript.

Jinja2

Jinja2 est un moteur de template très respecté.

Il utilise un langage de template basé sur du texte et peut donc être utilisé pour générer n’importe quel type de markup, et pas seulement du HTML. Il permet la personnalisation des filtres, de tags, de tests et des globals. Il dispose de nombreuses améliorations par rapport au système de template de Django.

Voici quelques balises html importantes dans Jinja2:

{# This is a comment #}

{# The next tag is a variable output: #}
{{title}}

{# Tag for a block, can be replaced through inheritance with other html code #}
{% block head %}
<h1>This is the head!</h1>
{% endblock %}

{# Output of an array as an iteration #}
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}

L’ensemble des listings suivants est un exemple de site web en combinaison avec le serveur web Tornado. Tornado est pas très compliqué à utiliser.

# import Jinja2
from jinja2 import Environment, FileSystemLoader

# import Tornado
import tornado.ioloop
import tornado.web

# Load template file templates/site.html
TEMPLATE_FILE = "site.html"
templateLoader = FileSystemLoader( searchpath="templates/" )
templateEnv = Environment( loader=templateLoader )
template = templateEnv.get_template(TEMPLATE_FILE)

# List for famous movie rendering
movie_list = [[1,"The Hitchhiker's Guide to the Galaxy"],[2,"Back to future"],[3,"Matrix"]]

# template.render() returns a string which contains the rendered html
html_output = template.render(list=movie_list,
                        title="Here is my favorite movie list")

# Handler for main page
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        # Returns rendered template string to the browser request
        self.write(html_output)

# Assign handler to the server root  (127.0.0.1:PORT/)
application = tornado.web.Application([
    (r"/", MainHandler),
])
PORT=8884
if __name__ == "__main__":
    # Setup the server
    application.listen(PORT)
    tornado.ioloop.IOLoop.instance().start()

Le fichier base.html peut être utilisé comme base pour toutes les pages du site qui sont par exemple implémentées dans le bloc de contenu.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{{title}} - My Webpage</title>
</head>
<body>
<div id="content">
    {# In the next line the content from the site.html template will be added #}
    {% block content %}{% endblock %}
</div>
<div id="footer">
    {% block footer %}
    &copy; Copyright 2013 by <a href="http://domain.invalid/">you</a>.
    {% endblock %}
</div>
</body>

Le prochain listing est notre page de site (site.html) chargé dans l’application Python qui étend base.html. Le bloc de contenu est automatiquement défini dans le bloc correspondant dans la page base.html.

<!{% extends "base.html" %}
{% block content %}
    <p class="important">
    <div id="content">
        <h2>{{title}}</h2>
        <p>{{ list_title }}</p>
        <ul>
             {% for item in list %}
             <li>{{ item[0]}} :  {{ item[1]}}</li>
             {% endfor %}
        </ul>
    </div>
    </p>
{% endblock %}

Jinja2 est la bibliothèque de templating recommandée pour les nouvelles applications Python web.

Chameleon

Les Page Templates de Chameleon sont l’implémentation dans un moteur de template HTML/XML des syntaxes Template Attribute Language (TAL), TAL Expression Syntax (TALES), et Macro Expansion TAL (Metal).

Chameleon est disponible pour Python 2.5 et plus (y compris 3.x et pypy), et est couramment utilisé par le Framework Pyramid.

“Page Templates” ajoute au sein de votre structure de document des éléments d’attributs spéciaux et du texte de markup. En utilisant un ensemble de constructions de langage simples, vous contrôlez le flux du document, la répétition d’élément , le remplacement de texte et de la traduction. A cause de la syntaxe basée sur des attributs, les templates de page non-rendus sont valides HTML et peuvent être regardés dans un navigateur et même édités dans des éditeurs WYSIWYG. Cela peut permettre la collaboration par aller-retour avec des designers et le prototypage avec des fichiers statiques dans un navigateur plus facile.

Le langage TAL de base est assez simple à comprendre à partir d’un exemple:

<html>
  <body>
  <h1>Hello, <span tal:replace="context.name">World</span>!</h1>
    <table>
      <tr tal:repeat="row 'apple', 'banana', 'pineapple'">
        <td tal:repeat="col 'juice', 'muffin', 'pie'">
           <span tal:replace="row.capitalize()" /> <span tal:replace="col" />
        </td>
      </tr>
    </table>
  </body>
</html>

Le pattern <span tal:replace=”expression” /> pour l’insertion de texte est suffisamment courant pour que vous ne demandiez pas une validité stricte dans vos templates non-rendus. Vous pouvez le remplacer par une syntaxe plus concise et lisible qui utilise le pattern ${expression}, comme suit:

<html>
  <body>
    <h1>Hello, ${world}!</h1>
    <table>
      <tr tal:repeat="row 'apple', 'banana', 'pineapple'">
        <td tal:repeat="col 'juice', 'muffin', 'pie'">
           ${row.capitalize()} ${col}
        </td>
      </tr>
    </table>
  </body>
</html>

Mais gardez à l’esprit que la syntaxe complète <span tal:replace=”expression”>texte par défaut</span> permet aussi d’avoir un contenu par défaut dans le modèle non-rendu.

Venant du monde Pyramid, Chameleon n’est pas largement utilisé.

Mako

Mako est un langage de template qui compile en Python pour une performance maximale. Sa syntaxe et son api sont empruntées des meilleures parties d’autres langages de templating comme les modèles Django et Jinja2. Il est le langage de template par défaut inclus avec les frameworks web Pylons et Pyramid.

Un template exemple en Mako ressemble à ceci:

<%inherit file="base.html"/>
<%
    rows = [[v for v in range(0,10)] for row in range(0,10)]
%>
<table>
    % for row in rows:
        ${makerow(row)}
    % endfor
</table>

<%def name="makerow(row)">
    <tr>
    % for name in row:
        <td>${name}</td>\
    % endfor
    </tr>
</%def>

Pour faire le rendu d’un template très basique, vous pouvez faire ce qui suit:

from mako.template import Template
print(Template("hello ${data}!").render(data="world"))

Mako est bien respecté au sein de la communauté web Python.

Références

[1]

Le projet mod_python est maintenant officiellement mort

[2]mod_wsgi vs mod_python
[3]

Benchmark de serveurs WSGI Python