[PYTHON] À propos de la personnalisation de Flask

Calendrier de l'Avent 2012 Python (Web Framework) Je suis en charge du 5ème jour de #python_adv. Cet article sera un multi-post avec mon blog. http://methane.hatenablog.jp/entry/2012/12/05/134206

Le flacon n'est pas un jouet

Les IDE tels que PyCharm ont commencé à prendre en charge Flask, et Flask devient suffisamment répandu pour être appelé le cadre Web n ° 2 pour Python après Django. (Bien que le support de Python3 soit lent pour cela)

Flask est célèbre pour sa capacité à écrire facilement le microframework Hello World.

hello.py


import flask
app = flask.Flask(__name__)
@app.route('/')
def index():
    return "Hello, World."
app.run(debug=True)

En regardant cela, cela ressemble à un jouet, mais Flask a une base solide qui vous permet de mettre plusieurs applications sur un interpréteur Python ou plusieurs instances d'une application, et c'est un module utilisant Blueprint. Il dispose également d'un cadre qui peut être utilisé pour des applications à grande échelle.

Par rapport au framework de type full stack, le point que les bibliothèques telles que OR mapper, la bibliothèque de formulaires et la bibliothèque de support AJAX ne sont pas intégrées est micro, mais si vous voulez choisir une telle bibliothèque vous-même, modifiez le framework de type full stack. Je pense qu'il est souvent plus facile d'étendre Flask que de le faire.

Aujourd'hui, je vais vous donner un aperçu rapide de la façon de personnaliser Flask pour chaque application. (Il est temps de créer une extension Flask modulaire comme Flask-SQLAlchemy)

Modèle de personnalisation

Il y a deux façons d'hériter et de personnaliser la classe Flask, et d'utiliser les méthodes de l'instance Flask, mais dans la plupart des cas, cette dernière suffira.

Il existe de nombreuses fonctions de personnalisation, mais il n'y a pas beaucoup de modèles pour les étendre, je vais donc vous montrer trois modèles.

Modifier directement les attributs de l'application

Par exemple, si vous préparez les variables utilisées dans la partie d'en-tête par défaut pour l'ensemble de l'application, c'est pratique car vous n'avez pas à définir les variables dans render_response à chaque fois. Flask fournit une méthode d'extension qui remplace create_jinja_environment, mais il est plus facile de l'ajouter directement à ce niveau.

import random
app.jinja_env.globals['random'] = random.randint

Cependant, sachez que jinja_env sera créé à l'aide de create_jinja_environment lors de son premier accès, le timing sera donc accéléré. Dans la plupart des cas, cela devrait être bien, mais si nécessaire, utilisez la méthode d'extension de style décorateur décrite ci-dessous.

@app.before_first_request
def extend_jinja_env():
    app.jinja_env.globals['random'] = random.randint

C'est une bonne idée de retarder l'arrivée de la première requête ou de remplacer create_jinja_environment normalement.

Puisqu'il n'y a qu'un seul environnement jinja pour chaque application, il n'est pas possible d'ajouter des variables pour chaque Blueprint. Dans ce cas, écrivez la fonction de rendu dans le module qui crée le plan.

def render(tmpl, **kw):
    kw['rnd'] = random.randrange(1000)
    return flask.render_response(tmpl, **kw)

Un exemple d'utilisation de la méthode de modification directe des attributs de l'application consiste à remplacer session_interface et à utiliser votre propre gestionnaire de session.

PS: J'ai pu ajouter des variables en utilisant les décorateurs context_processor de Flask et Blueprint. C'est également possible pour chaque Blueprint. C'est un bon moyen de stocker différentes valeurs pour chaque demande.

http://flask.pocoo.org/docs/templating/#context-processors

Extension avec des décorateurs

Si vous souhaitez afficher la date / heure avec le fuseau horaire +0 comme heure du Japon dans le modèle, par exemple lorsque l'heure est stockée en UTC dans la base de données bien qu'il s'agisse d'une application pour le Japon, vous pouvez ajouter un filtre comme celui-ci.

@app.template_filter()
def jptime(dt, format='%Y-%m-%d %H:%M:%S'):
    u"""Convertir l'heure utc en une chaîne au format spécifié par l'heure japonaise."""
    local = dt + datetime.timedelta(hours=9)
    return local.strftime(format)

Cela ressemble à ceci lors de son utilisation.

Dernière modification: {{ post.last_modified | jptime('%m/%d %H:%M') }}

@ app.template_filter n'est pas seulement un décorateur mais un décorateur de style fonction, mais vous pouvez écrire name =" JT " dans cet argument pour séparer le nom de la fonction du nom du filtre dans le modèle. ..

Il existe de nombreuses autres extensions qui utilisent des décorateurs. La plupart d'entre eux sont également disponibles dans Blueprint. Par exemple, un Blueprint requiert une authentification pour toutes les demandes.

from myapp.auth import auth
bp = flask.Blueprint('admin', __name__)

@bp.route('/')
@auth.required
def index():
    #…

@bp.route('/profile')
@auth.required
def profile():
    #…

Si vous enregistrez une fonction avec before_request, elle sera appelée avant d'appeler la fonction view. De plus, l'appel de la fonction de vue est ignoré lorsque cette fonction renvoie une réponse, vous pouvez donc utiliser le décorateur `` @ auth.required '' pour la fonction de vue.

bp = flask.Blueprint('admin', __name__)

@bp.before_request
@auth.required
def before_request():
    flask.g.user = auth.get_user()

#…

Il existe deux types de décorateurs d'extension Flask, l'un est un type de fonction et l'autre n'est qu'un décorateur, mais ne vous inquiétez pas, vous pouvez voir l'exception d'un seul coup en regardant la trace de la pile même si vous ne l'utilisez pas correctement.

Utiliser le contexte de l'application / le contexte de la demande

Les informations sur l'application en cours d'exécution et les informations sur la demande en cours de traitement, telles que flask.current_app et flask.request, sont gérées à l'aide d'une pile locale de thread appelée pile de contexte. Le but de la pile est de vous permettre d'exécuter d'autres applications Flask à partir de l'application Flask, et si vous souhaitez étendre une application, modifiez le contexte en haut de la pile.

Par exemple, supposons que vous souhaitiez vous connecter à la base de données pour chaque requête et vous déconnecter à la fin.

Dans ce cas, le contexte de requête convient, mais le contexte d'application, qui peut être facilement utilisé même à partir d'un script qui n'a pas de requête HTTP, est plus adapté.

def _connect_db():
    return MySQLdb(**app.config['MYSQL_OPTS'])

def get_db():
    top = flask._app_context_stack.top
    if top is None:
        raise RuntimeError('working outside of application context')
    if not hasattr(top, 'db'):
        top.db = _connect_db()
    return top.db

@app.teardown_appcontext
def _close_db():
    top = flask._app_context_stack.top
    if top is None:
        raise RuntimeError('working outside of application context')
    if hasattr(top, 'db'):
        top.db.close()
        top.db = None

Si vous voulez en faire juste une variable globale db au lieu d'appeler get_db () à chaque fois, utilisez LocalProxy.

from werkzeug.local import LocalProxy
db = LocalProxy(get_db)

Cependant, LocalProxy a une surcharge, vous pouvez donc ne pas vouloir l'utiliser si vous accédez fréquemment à des attributs des centaines de fois en une seule demande.

En pratique, il est plus facile d'utiliser la variable flask.g sur le contexte de la requête sans avoir à modifier directement le contexte. (Exemple: http://flask.pocoo.org/docs/patterns/sqlite3/)

Je pense qu'il suffit de traiter directement le contexte uniquement si vous souhaitez le réutiliser indépendamment de votre propre application, comme lors de la création d'une extension Flask.

N'utilisez pas flask.session

La session flask peut être personnalisée en remplaçant Flask.session_interface.

Cette personnalisation est assez simple, mais comme elle est appelée avant before_request, par exemple, si vous souhaitez générer un ID de session associé à un ID utilisateur dans une application qui nécessite une connexion, vous devez générer un objet de session avant l'authentification, ou Blueprint C'est gênant lorsque l'on souhaite contrôler en détail la gestion des sessions. Alors, voici comment désactiver flask.session.

app.session_interface = flask.sessions.NullSessionInterface()

Après cela, si vous mettez votre propre session dans flask.g.session etc. et définissez le comportement en utilisant before_request, teardown_request etc., vous pouvez contrôler la session plus librement. Par exemple, pour utiliser Beaker avec Flask, reportez-vous à http://flask.pocoo.org/snippets/61/ et personnalisez-le si nécessaire.

Recommended Posts

À propos de la personnalisation de Flask
ballon
ballon
À propos du traitement des paramètres dans le fichier request.args de Flask
À propos de LangID
À propos de CAGR
À propos de virtiofs
À propos de python-apt
À propos de sklearn.preprocessing.Imputer
À propos de Gunicorn
À propos de requirements.txt
Premier flacon
Mémo du flacon
À propos de l'axe = 0, axe = 1
À propos de l'importation
À propos de numpy
À propos de pip
À propos de Linux
À propos de numpy.newaxis
À propos d'Endian
À propos de Linux
À propos de l'importation
À propos de Linux
À propos de Linux
À propos de cv2.imread
À propos de _ et __
À propos de wxPython