Sortie de Flask 1.0

Posté par . Édité par Davy Defaud, Lucas, Xavier Claude, ZeroHeure, Yvan Munoz, Nÿco et Benoît Sibaud. Modéré par Yvan Munoz. Licence CC by-sa.
42
1
mai
2018
Python

Flask est un micro‐cadriciel Web pour Python publié sous licence BSD. Il est basé sur Werkzeug, Jinja2, MarkupSafe et ItsDangerous.

Logo de Flask

Bien que stable depuis longtemps, Flask passe finalement en version 1.0, huit ans après le début de son développement. Cette version aura demandé un an de travail et propose un grand nombre de modifications.

Liste des modifications

  • abandon de la prise en charge de Python 2.6 et 3.3 ;
  • l’interface en ligne de commande est plus flexible (voir la documentation en anglais pour en savoir plus) ;
  • si python-dotenv est installé, l’interface en ligne de commande chargera les variables d’environnement depuis les fichiers .flaskenv et .env plutôt que d’avoir à les exporter dans chaque nouveau terminal ;
  • le serveur de développement est par défaut à multiples fils d’exécution (multi‐thread) pour permettre de traiter des requêtes concurrentes pendant le développement ;
  • flask.ext, précédemment rendu obsolète, est maintenant complètement supprimé ; les importations d’extensions se font dorénavant par le nom de leur paquet ;
  • les messages d’erreur en mode débogage sont beaucoup plus explicites lorsque le développeur tente d’accéder à des clefs manquantes dans request.form ;
  • un truc trop bien avec les error handlers, qui sont maintenant recherchés par code puis par classe d’exception, d’abord dans le blueprint puis dans l’application ; cela donne un contrôle plus prévisible, avec notamment la possibilité de soulever une HTTPException ;
  • le comportement de app.logger a été grandement simplifié et devrait être plus facile à adapter. Le système de journalisation se nomme toujours flask.app, il ajoute un gestionnaire (handler) seulement s’il n’y en a pas d’enregistré ; en aucun cas il ne supprime de gestionnaires existants (voir la documentation, en anglais, pour en savoir plus) ;
  • test_client a maintenant un argument json pour envoyer des données JSON et l’objet Response a maintenant une méthode get_json pour décoder les données comme du JSON dans les tests ;
  • un nouveau test_cli_runner a été ajouté pour tester l’interface en ligne de commande d’une application ;
  • plusieurs parties de la documentation ont été réécrites pour être plus claires et pertinentes, c’est un effort continu ;
  • le tutoriel et l’exemple correspondant ont été réécrits, ils utilisent un plan structuré et permettent d’aller dans le détail de chaque aspect afin d’aider les nouveaux utilisateurs à éviter les problèmes communs.

Plusieurs autres modifications ont été faites et apparaissent dans la liste complète des modifications (en anglais).

Correctif de sécurité pour JSON

Précédemment, Flask décodait les entrées JSON en utilisant le type de contenu de la requête. Bien que ces entrées devaient être uniquement codées en UTF-8, Flask était indulgent. Vu qu’il existe en Python des codages non textuels, cela pouvait entraîner une utilisation de la mémoire non désirée. Dorénavant, Flask détectera le codage des données JSON seulement parmi les formats Unicode pris en charge et n’autorisera plus d’autres types de codage.

Démonstration du cadriciel

Voici le fichier hello.py :

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Bonjour les moules< !"

Installation (ou mise à jour) et exécution

  • installation ou mise à jour depuis PyPI avec pip :

    $ pip install -U Flask

  • exécution de l’exemple de code :

    $ FLASK_APP=hello.py flask run

  • aller voir http://localhost:5000/.

Participer au projet

Comme beaucoup de projets libres, Flask et l’équipe Pallets sont dépendants de la communauté. Rapporter des problèmes, écrire de la documentation, proposer des correctifs ou répondre aux questions sont autant d’aides qui seront appréciées à leurs justes valeurs. Voir le guide de la contribution (en anglais) pour plus d’information.

De plus, l’association Pallets vient de rejoindre le programme Fiscal Sponsorship de la fondation Python Software.

Ils acceptent maintenant les dons via la fondation Python Software pour soutenir leurs efforts de développement du projet et de la communauté. Cliquer ici pour donner.

  • # Position par rapport à Django ?

    Posté par . Évalué à 6.

    Je suis totalement béotien en python et encore plus en python web.

    Mais quelle est la position de ce cadriciel par rapport à Django ? Le remplace-t-il ? Si oui, quels sont ses avantages et inconvénients par rapport à celui-ci ?

    • [^] # Re: Position par rapport à Django ?

      Posté par (page perso) . Évalué à 10.

      De mon point de vue, Flask se veut plus modulaire. De base, Django vient avec son système d'authentification, son ORM, son templating, tandis que Flask n'impose rien. Du coup, si c'est pour faire une application de base avec un ORM et du templating, sans besoin spécifique, autant partir sur Django. Si on a des besoins spécifiques (pas d'ORM ou un particulier, un système de templating particulier…), autant partir sur Flask.

      Après, si on est déjà habitué à l'un ou l'autre, on peut toujours les adapter.

      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: Position par rapport à Django ?

      Posté par . Évalué à 3. Dernière modification le 01/05/18 à 14:40.

      Je pense que ça vas dépendre de ton projet et de sa complexité, pour un truc 'tout con' flask est parfait à l'inverse django seras plus utile sur une app plus poussé.

      Ce n'est pas un jugement de valeur hein, tu pourrais faire la même chose avec les deux framework.

      Allez tous vous faire spéculer.

      • [^] # Re: Position par rapport à Django ?

        Posté par . Évalué à 3.

        J'aurais presque dit le contraire. Il faudrait définir "un truc tout con" pour être d'accord avec toi.

        Django est livré "avec les piles". Tu peux faire des trucs classiques sans rien avoir à installer en plus. Tu peux aller rapidement à l'essentiel… si ce que tu fais est "classique".

        Flask est livré "nu". Si tu veux faire un truc classique avec il faut commencer par installer des modules pour gérer la base de données, les sessions, l'administration, … (ou alors tu redéveloppes tout toi même)

        Par contre pour faire des trucs plus exotiques, les piles des fois c'est pas nécessaire. Genre si tu fais du solaire ;-)

        • [^] # Re: Position par rapport à Django ?

          Posté par . Évalué à 5.

          C'est surtout pas la bonne dichotomie à mon avis. C'est plus la volonté du développeur qui va faire choisir entre ces 2 formes de frameworks.

          Soit on pars d'un truc minimaliste et on construit dessus. Ça permet de rendre explicite tout ce qui se passe et d'avoir peu de convention. Mais il peut être plus compliqué de rentrer dans le code car, justement, il a ses propres conventions. Ça peut aussi être plus compliqué, il peut y avoir des bugs subtils car l'intégration de la façon de gérer la base de données et les contrôleurs web ne correspond pas vraiment. La maintenance dans le temps peu aussi être plus complexe : mettre à jour une bibliothèque peu casser toute son intégration.

          Soit on pars de quelque chose qui fait tout. On arrive alors avec un truc qui fait beaucoup de choses et qui va sembler facile de prime abord, mais il est important de comprendre ce qu'il se passe. On va lourdement s'appuyer sur des conventions. Cela va implicitement faire des choix qui ne sont pas toujours les plus pertinents pour ce que l'on fait. Il est potentiellement plus simple de rentrer dans le code car tout projet utilisant ce type de framework aura la même tête. Enfin la maintenance peut être simplifié car la mise à jour se fait via le framework qui va arriver comme un tout et donc mieux documenter les évolutions. La customisation de certains élément peut, par contre être plus complexe (elle demande généralement à bien comprendre le framework).

          C'est ce qui va distinguer les microframeworks comme Flask ou Sinatra des gros framework comme Django ou Rails.

          • [^] # Re: Position par rapport à Django ?

            Posté par (page perso) . Évalué à 9.

            Pour compléter ce que tu dis…

            Soit on pars d'un truc minimaliste et on construit dessus. Ça permet de rendre explicite tout ce qui se passe […].

            Ce qui rend le code compréhensible par tout développeur connaissant le langage mais pas forcément les bibliothèques utilisées.

            Mais il peut être plus compliqué de rentrer dans le code car, justement, il a ses propres conventions. Ça peut aussi être plus compliqué, il peut y avoir des bugs subtils car l'intégration de la façon de gérer la base de données et les contrôleurs web ne correspond pas vraiment. La maintenance dans le temps peu aussi être plus complexe : mettre à jour une bibliothèque peu casser toute son intégration.

            La maintenance d'une appli django est très compliquée. Les fonctionnalités de Django évoluent vite, et comme c'est basé sur des conventions qui changent/s'enrichissent, c'est très difficile de savoir ce qui est disponible et ce qui ne l'est pas sur une application donnée. Par ailleurs, les conventions et la "magie" de Django rendent des sujets a priori simples très compliqués à comprendre pour quelqu'un qui ne connait pas ou peu le framework.

            Je vais prendre juste un exemple : Django propose un mécanisme de signaux pour exécuter des "triggers". C'est chouette ça simplifie l'écriture du code et tu arrives rapidement à l'objectif. Mais à lire/relire/maintenir/faire évoluer c'est une autre histoire.

            Django est très bien si tu fais du pur développement web (par exemple : l'idée de réutiliser des briques de code ailleurs que dans un contexte web, c'est pas vraiment fait pour… et l'archi de Django ne t'incite pas à découper ton code en vue/logique/modèle ). Si tu es dans un environnement partiellement hors web, j'aurais tendance à ne pas partir sur un Django.

            L'avantage de Django, c'est que si tu fais des choses web "classiques", tu vas hyper vite car tout est fait pour (modules disponibles, comportements par défaut correspondant à 90% des cas d'utilisation). A un moment leur tagline était qqchose comme "Django, the web application framework for projects with deadlines". En gros pour écrire vite (et si possible bien). Et ça marche bien dans ce contexte. Par exemple la gestion des migrations de modèles de base de données, les interfaces d'admin… c'est du clé-en-main. Et tu as une communauté qui créé des modules ou applications pour django qui te permettent de construire en assemblant des briques.

            Mais si tu veux sortir des sentiers battus (ou prévoit de le faire), avec Django tu vas tordre ta logique de développeur pour la faire rentrer dans le moule Django et non l'inverse. Et ça, c'est pas forcément une bonne idée.

            La customisation de certains élément peut, par contre être plus complexe (elle demande généralement à bien comprendre le framework).

            La moindre sortie de la route tracée par Django rend le code extrêmement plus complexe.

            C'est ce qui va distinguer les microframeworks comme Flask ou Sinatra des gros framework comme Django ou Rails.

            Pour compléter (ou reformuler) : un framework comme Flask va te laisser choisir les briques que tu assembles, en te proposant des solutions standards (par exemple : associer SQLAlchemy avec Flask) mais pas obligatoires. Ces solutions sont de la documentation que tu vas décider de suivre ou pas. Dans un framework comme Django ça sera inclut d'office, voire difficile à remplacer si tu veux utiliser autre chose.

    • [^] # Re: Position par rapport à Django ?

      Posté par . Évalué à 3.

      Il y a grosso modo une hiérarchie (falcon) bottle < flask < pyramid < django où tout est de plus en plus intégré et de plus en plus consommateur en ressources (le nombre de requêtes pouvant être traité diminuant de plus en plus).

      Django est très bien si tu est intéressé par un framework clé en main où tout est plus ou moins traité et standardisé, on peut par exemple intégrer n'importe qu'elle application Django avec Django CMS. On peut faire un parallèle avec un ERP genre Odoo qui est encore plus intégré.

      Par contre si tu veux développer un backend (api rest) supportant une très grosse charge, Django ne sera clairement pas le framework adapté.

      Django est aussi un framework de la vielle école dans le sens où il a été conçu pour concurrencer php à une époque où les api rest, frontend js et websocket n'existaient pas. Je ne suis pas sûr que Django soit adapté pour un projet comme Taiga.

      Pour résumer c'est comme pour une pelleteuse, tu ne fais pas le même travail avec un modèle de 500 kg et un de 50 tonnes.

      • [^] # Re: Position par rapport à Django ?

        Posté par . Évalué à 2.

        On utilise Flask pour faire de l'API REST et mon collègue me faisait remarquer aujourd'hui qu'à peu de choses près, on pourrait utiliser Werkzeug directement. Par exemple, on utilise pas ou à peine le templating jinja.

        Je sais pas si ça serait plus performant, et l'utilisation de Flask donne accès à pas mal d'extensions existantes qu'on a pas envie de dupliquer.

  • # Juste un détail...

    Posté par . Évalué à 4.

    D'abord merci pour cette dépêche. Ceci dit et pour être complet, si l'exemple a l'air intuitivement facile à comprendre, ç'aurait été intéressant de mentionner/rappeler ce que fait le décorateur

    @app.route("/")
    dans cette histoire.

    • [^] # Re: Juste un détail...

      Posté par . Évalué à 3.

      Un code simple n'a pas besoin d'être commenté, la fonction du décorateur me parait évidente à priori.

      Ce serais plus pertinent d'expliquer ce qu'est un décorateur, un débutant ce questionnera plus sur son fonctionnement que sur son but à mon avis.

      Allez tous vous faire spéculer.

      • [^] # Re: Juste un détail...

        Posté par . Évalué à 3.

        Un code simple n'a pas besoin d'être commenté, la fonction du décorateur me parait évidente à priori.

        Ben a priori j'ai pas compris à quoi ça sert (ou à peine mais je peine aussi à comprendre pourquoi ce décorateur s'appelle ainsi, si c'est pour faire ce que je crois qu'il fait). D'où mon commentaire.

        De plus je ne partage pas ton avis: Flask est écrit en Python, ce qui devrait présupposer que le lecteur sait ce qu'est un décorateur. Et quand bien même, c'est de toute façon hors de propos: un décorateur n'est en rien spécifique à Flask, qui, lui est le sujet de la dépêche, d'où expliciter ce que @app.route fait et pourquoi il s'appelle comme ça me paraît pertinent.

        • [^] # Re: Juste un détail...

          Posté par . Évalué à 10.

          Le décorateur route() sert à lier une URL à une fonction.

          @app.route("/")
          def hello():
              return 'Bonjour depuis la racine du site'

          Dans l'exemple ci-dessus, si quelqu'un appelle la racine de ton application ("/"), Flask exécutera la fonction hello().

          Tu peux aussi faire des choses comme suit :

          @app.route('/utilisateur/<username>')
          def hello_user(username):
              return 'Bonjour %s !' % username
          • [^] # Re: Juste un détail...

            Posté par . Évalué à 2.

            Je comprends pas :(

            Tu pourrais nous faire un exemple avec 3 routes stp ?
            - 2 routes fixe /foo et /bar
            - 1 route avec un parametre style /id/ ?

            Je ne comprends pas le lien entre la fonction et la définition de la route. Je ne vois nulle part "pour telle route, appelle telle callback".

            Merci :)

            • [^] # Re: Juste un détail...

              Posté par . Évalué à 9.

              Je ne comprends pas le lien entre la fonction et la définition de la route. Je ne vois nulle part "pour telle route, appelle telle callback".

              C'est tout l'objet du décorateur "@app.route", pour être plus explicite le code python serait :

              from flask import Flask
              app = Flask(__name__)
              
              @app.route('/')
              def hello_world():
                  return 'Hello, World!'
              
              @app.route('/foobar')
              def hello_world():
                  return 'Foobar...'
              
              @app.route('/foo/', defaults={'id': 1})
              @app.route('/foo/<id>', methods=['GET', 'POST'])
              def foo(id):
                  return 'Foo %s' % id

              Le décorateur @app.route('/') porte sur la fonction définit juste en dessous donc ici hello_world, c'est de cette façon que le "callback" est défini. Plusieurs décorateurs peuvent être définis pour une fonction comme pour foo().

              On peut aussi faire le routage avec la syntaxe:

              from flask import Flask
              app = Flask(__name__)
              
              def index():
                  return 'Hello, World!'
              
              # ...
              
              app.add_url_rule('/', 'index', index)

              D'ailleurs @app.route() appelle app.add_url_rule()

              • [^] # Re: Juste un détail...

                Posté par . Évalué à 4.

                Copier/coller malencontreux…
                Il ne peut bien sûr pas y avoir 2 définitions de hello_world() la 2e devrait être def foobar()

            • [^] # Re: Juste un détail...

              Posté par . Évalué à 4.

              Comme expliqué par Jerome, le décorateur est lié à la fonction qui le suit, tout simplement.

              @app.route("/foo")
              def peu_importe_le_nom_de_la_fonction():
                  return 'Je suis sur http://localhost:5000/foo !'
              
              @app.route("/bar")
              def une_autre_fonction():
                  return 'Je suis sur http://localhost:5000/bar !'
              
              @app.route('/id/<spamspam>')
              def display_id(spamspam):
                  return 'Mon identifiant est %s !' % spamspam
              
              @app.route("/plop")
              @app.route("/glop")
              def encore_une_autre_fonction():
                  return 'Je peux arriver sur cette page de 2 façons : http://localhost:5000/plop ou http://localhost:5000/glop !'

              Tu trouveras plus de détails basiques sur la page "quickstart" du projet : http://flask.pocoo.org/docs/1.0/quickstart/ (en anglais)

          • [^] # Re: Juste un détail...

            Posté par . Évalué à 4.

            Merci beaucoup pour tes exemples, dovik. Maintenant c'est tout-à-fait clair.

  • # Tutoriel Flask

    Posté par . Évalué à 5.

    Merci pour cette dépêche !

    Pour ceux que ça intéresse, Miguel Grinberg a écrit une très bonne série d'articles sur Flask (en anglais).

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.