Partage de modèles, de classes, de Blueprints et de modèles entre applications avec Flask DispatcherMiddleWare
En évitant la duplication, votre code devient plus petit et plus facile à maintenir.
Ce site fonctionne sous Flask. Il utilise DispatcherMiddleWare pour exécuter l'application frontale et l'application d'administration. Les documents Flask indiquent que les applications Flask sont, dans ce cas, entièrement isolées les unes des autres. C'est vrai, mais il y a souvent beaucoup de code que nous voulons partager entre ces applications.
Ce que nous voulons partager
Les deux applications utilisent la même base de données, ce qui signifie que nous voulons partager le fichier models.py. Ensuite, nous avons certaines classes que nous avons écrites nous-mêmes. Par exemple, j'ai écrit des classes comme MailMessage et FormValidation. Elles doivent être utilisées par les deux applications.
J'utilise également Blueprints qui devrait être partagé, par exemple l'"auth" Blueprint qui gère les fonctions d'authentification comme la connexion, la création de compte, la réinitialisation du mot de passe. Les modèles utilisés par ces Blueprints doivent également être partagés. Il existe également d'autres modèles qui doivent être partagés, comme les macros permettant de mettre des formulaires sur une page, les macros permettant de mettre des boutons dans des tableaux.
Ajout d'un répertoire partagé
Dans un article précédent, j'ai parlé de l'utilisation de DispatcherMiddleware et j'ai présenté une structure de répertoire de base. Il est maintenant temps d'ajouter un répertoire partagé, voir ci-dessous.
|
|-- project
| |-- alembic
| | `--
| |
| |-- app_admin
| | |-- __init__.py
| | |-- blueprints
| | | |-- content_item
| | | | |-- forms.py
| | | | |-- __init__.py
| | | | `-- views.py
| | | |-- user
| | | | |-- forms.py
| | | | |-- __init__.py
| | | | `-- views.py
| | |-- templates
| | | |-- content_item
| | | | |-- content_items_list.html
| | | | `--
| | | |-- user
| | | | |-- users_list.html
| | | | `--
| | | |-- base.html
| | `-- translations
| | `-- es_ES
| | `-- LC_MESSAGES
| | |-- messages.mo
| | `-- messages.po
| |
| |-- app_frontend
| | |-- __init__.py
| | |-- blueprints
| | | |-- comments
| | | | |-- forms.py
| | | | |-- __init__.py
| | | | `-- views.py
| | | `-- demo_crud_view_uuid
| | | |-- forms.py
| | | |-- __init__.py
| | | `-- views.py
| | |-- templates
| | | |-- comments
| | | | |-- comment_form.html
| | | | `--
| | | `-- base.html
| | `-- translations
| | `-- es_ES
| | `-- LC_MESSAGES
| | |-- messages.mo
| | `-- messages.po
| |
| |-- shared
| | |-- blueprints
| | | |-- account
| | | | |-- forms.py
| | | | |-- __init__.py
| | | | `-- views.py
| | | `-- auth
| | | |-- forms.py
| | | |-- __init__.py
| | | `-- views.py
| | |-- static
| | | |-- blog
| | | |-- css
| | | |-- js
| | | |-- vendor
| | | `-- robots.txt
| | |-- templates
| | | |-- account
| | | | `-- overview.html
| | | |-- auth
| | | | `-- login.html
| | | |-- macros
| | | | `--
| | | `-- boxed.html
| | |
| | |-- constants.py
| | |-- class_app_mail.py
| | |-- class_input_validation.py
Modifications du dossier statique
J'ai déjà une variable d'environnement qui contient le répertoire statique. La raison est que le répertoire statique se trouve à un endroit différent sur le système de production. Dans la fonction create_app() des applications app_frontend et app_admin , nous créons l'application Flask avec le même répertoire statique :
flask_static_folder = os.getenv('FLASK_STATIC_FOLDER')
app = Flask(
__name__,
static_folder=flask_static_folder,
)
Modifications des importations
Bien entendu, nous devons apporter des modifications aux importations initiales. Par exemple, dans les fichiers app_frontend Python , nous modifions les importations des fichiers Python de :
# register blueprints
# authentication (shared)
from .blueprints.auth.views import auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/<lang_code>/auth')
à :
# register blueprints
# authentication (shared)
from shared.blueprints.auth.views import auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/<lang_code>/auth')
Modifications apportées à template_folders
C'est un peu magique. Je n'ai pas spécifié de template_folder lors de la création de l'application Flask , ce qui signifie que Flask utilise le dossier "templates" par défaut. Mais comment pouvons-nous accéder aux modèles partagés ? Heureusement, nous pouvons spécifier un répertoire "templates" lorsque nous créons une application Blueprint. Si vous le spécifiez :
auth_blueprint = Blueprint('auth', __name__, template_folder='templates')
Si vous ne pouvez pas les utiliser, vous dites à Flask qu'il y a un répertoire "templates" dans le répertoire "auth" de Blueprint . Ce répertoire est relatif ( !) au répertoire "auth" Blueprint . La structure du répertoire doit donc être la suivante :
| |-- shared
| | |-- blueprints
| | | `-- auth
| | | |-- forms.py
| | | |-- __init__.py
| | | |-- views.py
| | | `-- templates
| | | `-- auth
| | | |-- login.html
| | | `--
Notez qu'il y a un répertoire supplémentaire "auth" dans le répertoire des modèles car nous ne voulons pas modifier le fichier views.py. Ce fichier contient des fonctions d'affichage se terminant par :
...
return render_template(
'auth/login.html',
...
Si nous procédons de cette manière, nous obtenons un répertoire modèle pour chaque Blueprint partagé, ce qui n'est pas vraiment ce que nous voulons. Le répertoire de modèles partagé doit avoir la même structure que les répertoires de modèles app_frontend et app_admin , un seul répertoire avec des sous-répertoires pour chaque Blueprint. Pour y parvenir, nous modifions le Blueprint template_folder pour qu'il pointe vers le shared/templates :
auth_blueprint = Blueprint('auth', __name__, template_folder='../../templates')
Nous faisons cela pour tous les Blueprints partagés et nous avons terminé. Ce qui est magique, c'est que vous n'avez à le faire que pour un seul Blueprint partagé. On dirait que Flask est en train de construire une liste de répertoires de recherche de modèles et une fois que nous avons traité la template_folder pour l'"auth" Blueprint , le chemin est ajouté à cette liste et les autres Blueprints partagées trouvent également leurs modèles. Dans la documentation Flask : "Le dossier de modèles (Blueprint) est ajouté au chemin de recherche des modèles, mais avec une priorité inférieure à celle du dossier de modèles de la demande réelle".
Cela fonctionne car dans ce cas, nous nous référons à un seul répertoire de modèles partagés, mais je préférerais pouvoir spécifier une liste de chemins de recherche de modèles au niveau de l'application. Vous trouverez des informations sur la manière de procéder, voir les liens ci-dessous.
Traductions
Lorsque vous avez un site multilingue et que vous utilisez Babel , vous devez vous assurer que les traductions de app_frontend ne sont pas seulement générées à partir du répertoire app_frontend mais aussi à partir du répertoire partagé. Il en va de même pour le répertoire app_admin. Pour ce faire, nous ajoutons le répertoire au fichier babel_app_frontend.cfg :
[python: app_frontend/**.py]
[python: shared/**.py]
[jinja2: app_frontend/templates/**.html]
[jinja2: shared/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_
encoding = utf-8
Résumé
Le partage de fichiers entre les applications Flask DispatcherMiddleWare rend votre travail beaucoup plus facile, sans doublons. J'ai eu quelques difficultés avec les modèles partagés. Vous devez vraiment prendre un certain temps pour comprendre cela. Finalement, j'ai créé un test et j'ai suivi le flux dans le code Jinja .
Le partage de fichiers n'a pas semblé si difficile, il commence par une solide structure de répertoires. Cela prouve une fois de plus les capacités de Flask. Aucun piratage n'est nécessaire, tout est déjà là.
Liens / crédits
Application Dispatching
https://flask.palletsprojects.com/en/1.1.x/patterns/appdispatch/
flask blueprint template folder
https://stackoverflow.com/questions/7974771/flask-blueprint-template-folder
Modular Applications with Blueprints
https://flask.palletsprojects.com/en/1.1.x/blueprints/#modular-applications-with-blueprints
Two Flask apps, frontend and admin, on one domain using DispatcherMiddleware
http://127.0.0.1:8000/en/blog/two-flask-apps-frontend-and-admin-on-one-domain-using-dispatchermiddleware
En savoir plus...
DispatcherMiddleWare Flask
Récent
- Don't Repeat Yourself (DRY) avec Jinja2
- SQLAlchemy, PostgreSQL, nombre maximal de lignes par user
- Afficher les valeurs des filtres dynamiques SQLAlchemy
- Transfert de données sécurisé grâce au cryptage à Public Key et à pyNaCl
- rqlite : une alternative à haute disponibilité et dist distribuée SQLite
- Dois-je migrer mon Docker Swarm vers Kubernetes ?
Les plus consultés
- Utilisation des Python's pyOpenSSL pour vérifier les certificats SSL téléchargés d'un hôte
- Utiliser UUIDs au lieu de Integer Autoincrement Primary Keys avec SQLAlchemy et MariaDb
- Connexion à un service sur un hôte Docker à partir d'un conteneur Docker
- SQLAlchemy : Utilisation de Cascade Deletes pour supprimer des objets connexes
- Utiliser PyInstaller et Cython pour créer un exécutable Python
- Flask RESTful API validation des paramètres de la requête avec les schémas Marshmallow