angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Обмен моделями, классами, Blueprints и шаблонами между приложениями с Flask DispatcherMiddleWare

Избегая дублирования, ваш код становится меньше по размеру и более удобен в обслуживании.

12 мая 2020
post main image
https://unsplash.com/@michel_catalisano

На этом сайте запущен Flask. Он использует DispatcherMiddleWare для запуска приложения фронтэнда и приложения администрирования. В документах Flask указано, что приложения Flask в этом случае полностью изолированы друг от друга. Это верно, но часто между этими приложениями есть много кода, которым мы хотим поделиться.

Вещи, которыми мы хотим поделиться

Оба приложения используют одну и ту же базу данных, то есть мы хотим поделиться файлом models.py. Тогда у нас есть определенные классы, которые мы сами написали. Например, я написал классы MailMessage и FormValidation. Они должны использоваться обоими приложениями.

Я также использую Blueprints , который должен быть разделен, например 'auth' Blueprint , обрабатывающий функции аутентификации, такие как вход в систему, создание учетной записи, сброс пароля. Шаблоны, используемые этими Blueprints также должны быть общими. Есть также другие шаблоны, которые должны быть общими, такие как макросы для размещения форм на странице, макросы для размещения кнопок в таблицах.

Добавление разделяемой директории

В предыдущей заметке я писал об использовании DispatcherMiddleware и представил базовую структуру каталога. Теперь пришло время добавить разделяемый каталог, см. ниже.

|
|-- 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

Изменения статической папки

У меня уже есть переменная окружения, которая содержит статический каталог. Причина в том, что статический каталог находится в другом месте в производственной системе. В create_app() обоих приложений app_frontend и app_admin мы создаем приложение Flask со статической директорией:

    flask_static_folder = os.getenv('FLASK_STATIC_FOLDER')
    app =  Flask(
        __name__, 
        static_folder=flask_static_folder,
    )

Изменения импорта

Конечно, мы должны внести изменения в жизненно важный импорт. Например, в файлах app_frontend Python мы изменяем импорт файлов Python :

    # 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')

Изменения в template_folders

Это немного волшебно. Я не указывал template_folder при создании приложения Flask , имеющего в виду Flask использует папку 'templates' по умолчанию. Но как мы можем получить доступ к общим шаблонам? К счастью, мы можем указать каталог 'templates' когда создаем Blueprint. Если вы укажете:

auth_blueprint  =  Blueprint('auth', __name__,  template_folder='templates')

затем вы сообщаете Flask , что в Blueprint есть каталог 'шаблонов' 'auth'. Эта директория является относительной (!) к директории Blueprint 'auth'. Тогда структура каталога должна быть такой:

|   |-- shared
|   |   |--  blueprints
|   |   |   `-- auth
|   |   |       |-- forms.py
|   |   |       |-- __init__.py
|   |   |       |--  views.py
|   |   |       `-- templates
|   |   |           `-- auth
|   |   |               |-- login.html
|   |   |               `-- 

Обратите внимание, что в каталоге шаблонов есть additonal directory 'auth', потому что мы не хотим изменять файл views.py. Этот файл содержит функции представления, заканчивающиеся на:

    ...
    return  render_template(
        'auth/login.html',
        ...

Если мы будем действовать таким образом, то получим каталог шаблонов для каждого разделяемого Blueprint. на самом деле это не то, что нам нужно. Каталог разделяемых шаблонов должен иметь такую же структуру, как каталоги шаблонов app_frontend и app_admin , единственный каталог с подкаталогами для каждого Blueprint. Для этого мы изменяем Blueprint template_folder на shared/templates:

auth_blueprint  =  Blueprint('auth', __name__,  template_folder='../../templates')

Мы делаем это для всех разделяемых Blueprints , и все готово. Волшебство заключается в том, что это нужно сделать только для одного общего Blueprint. Похоже, что Flask строит список каталогов поиска шаблонов, и как только мы обработаем template_folder для 'auth' Blueprint , путь добавляется в этот список, а другие общие Blueprints также находят свои шаблоны. Из документации Flask : 'Папка шаблонов (Blueprint) добавлена в путь поиска шаблонов, но с более низким приоритетом, чем папка шаблонов реального приложения'.
Это работает, потому что в данном случае мы ссылаемся на единственную общую папку шаблонов, но я бы предпочел иметь возможность указать путь поиска шаблонов на уровне приложения. Есть информация о том, как это сделать, смотрите ссылки ниже.

Переводы

Когда у вас мультиязычный сайт и вы используете Babel , вы должны убедиться, что переводы app_frontend генерируются не только из директории app_frontend , но и из директории общего доступа. То же самое относится и к app_admin. Для достижения этого мы добавляем директорию в файл 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

Резюме

Обмен файлами между приложениями Flask DispatcherMiddleWare делает вашу работу намного проще, без дубликатов. Я немного поборолся с общими шаблонами. Вам действительно нужно некоторое время, чтобы понять это. В конце концов я создал тест и последовал за ним в коде Jinja .

Обмен файлами оказался не таким уж сложным, он начинается со сплошной структуры каталога. Это еще раз доказывает возможности Flask. Взломать не надо, все уже есть.

Ссылки / кредиты

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

Оставить комментарий

Комментируйте анонимно или войдите в систему, чтобы прокомментировать.

Комментарии

Оставьте ответ

Ответьте анонимно или войдите в систему, чтобы ответить.