Вопрос или проблема
На StackExchange есть десятки вопросов о пропадающих маршрутах, но это может быть самым кратким примером. Предположим, что app.py находится в верхней папке, а __init__.py и т.д. находятся в подпапке “test”. Следующий код не работает:
app.py
from test_bad import create_app
# Запуск приложения
if __name__ == '__main__':
app = create_app()
for rule in app.url_map.iter_rules():
print(rule)
app.run(debug=True, use_reloader=False)
__init__.py
from flask import Flask, render_template
from . routes import dash
def create_app():
app = Flask(__name__)
app.register_blueprint(dash)
return app
routes.py
from flask import Blueprint
# Определение маршрута
dash = Blueprint('dash', __name__)
views.py
from . routes import dash
@dash.route("https://stackoverflow.com/", methods=['GET', 'POST'])
def index():
return '<html><body><h1>Привет, мир!</h1></body></html>'
@dash.route('/verify', methods=['GET','POST'])
def check_verification():
return '<html><body><h1>И прощай!</h1></body></html>'
в то время как следующий код работает без проблем:
app.py
from test_good.views import create_app
# Запуск приложения
if __name__ == '__main__':
app = create_app()
for rule in app.url_map.iter_rules():
print(rule)
app.run(debug=True, use_reloader=False)
__init__.py
routes.py
from flask import Blueprint
# Определение маршрута
dash = Blueprint('dash', __name__)
views.py
from flask import Flask, render_template
from . routes import dash
@dash.route("https://stackoverflow.com/", methods=['GET', 'POST'])
def index():
return '<html><body><h1>Привет, мир!</h1></body></html>'
@dash.route('/verify', methods=['GET','POST'])
def check_verification():
return '<html><body><h1>И прощай!</h1></body></html>'
def create_app():
app = Flask(__name__)
app.register_blueprint(dash)
return app
Смотря на напечатанные правила конечных точек, можно увидеть, что в “плохом” случае эти конечные точки не были добавлены в приложение (или приложение “обновилось” каким-то образом). В то время как в хорошем случае конечные точки в порядке.
С точки зрения структуры кода, я бы подумал, что __init__ – это правильное место, но, похоже, это не так.
Какой еще лучший способ написать это? [Или я что-то упустил]. Спасибо,
Ответ или решение
Проблема, с которой вы столкнулись, касается порядка регистрации маршрутов для ваших Blueprint в приложении Flask. Давайте разберем, почему примеры, которые вы привели, работают по-разному и как это лучше организовать.
Причина проблемы
В первом случае, где у вас есть __init__.py
, регистрирующий Blueprint, а обработчики маршрутов находятся в views.py
, происходит следующее:
-
Когда вы импортируете
dash
изroutes.py
в__init__.py
, вы создаете сам Blueprint, но маршруты, определенные вviews.py
, не связываются с этим Blueprint. Это происходит потому, что вашviews.py
фактически не выполняется до тех пор, пока приложение не будет выполнено, и обработчики маршрутов не будут добавлены к Blueprint. -
В результате, когда вы вызываете
create_app
в вашемapp.py
, Flask не "знает" о маршрутах, так как они не были загружены до регистрации Blueprint. Это и есть основная причина, почему ваши маршруты не отображаются вurl_map
.
Как это исправить
Чтобы исправить это, нужно убедиться, что маршруты загружаются до регистрации Blueprint. Один из распространенных подходов — это изменить порядок импортов и регистрации так, чтобы views.py
был импортирован после создания Blueprint. Вот как это можно сделать:
Предложенная структура
app.py
from test import create_app
# Запуск приложения
if __name__ == '__main__':
app = create_app()
for rule in app.url_map.iter_rules():
print(rule)
app.run(debug=True, use_reloader=False)
test/init.py
from flask import Flask
from .routes import dash
from .views import * # Импортируем views после определения dash
def create_app():
app = Flask(__name__)
app.register_blueprint(dash)
return app
test/routes.py
from flask import Blueprint
# Определяем Blueprint
dash = Blueprint('dash', __name__)
test/views.py
from .routes import dash
@dash.route("https://stackoverflow.com/", methods=['GET', 'POST'])
def index():
return '<html><body><h1>Hello World!</h1></body></html>'
@dash.route('/verify', methods=['GET', 'POST'])
def check_verification():
return '<html><body><h1>And Farewell!</h1></body></html>'
Альтернативный подход
Также можно оставить структуру как есть, но объявить и зарегистрировать маршруты сразу в routes.py
(в рамках одного файла routes.py
) вместо views.py
. Это может выглядеть следующим образом:
test/routes.py
from flask import Blueprint
# Определяем Blueprint
dash = Blueprint('dash', __name__)
@dash.route("https://stackoverflow.com/", methods=['GET', 'POST'])
def index():
return '<html><body><h1>Hello World!</h1></body></html>'
@dash.route('/verify', methods=['GET', 'POST'])
def check_verification():
return '<html><body><h1>And Farewell!</h1></body></html>'
Такой подход более интуитивен, поскольку маршруты и их обработчики находятся в одном файле, что упрощает управление.
Заключение
Важно помнить, что порядок импортов и структуру приложения в Flask необходимо тщательно контролировать. Если вы сталкиваетесь с проблемами регистрации маршрутов, всегда проверяйте, что все необходимые компоненты загружены до выполнения регистрации. Надеюсь, это поможет решить проблему! Если у вас есть дополнительные вопросы, не стесняйтесь задавать.