Почему мои чертежи не регистрируются при инициализации?

Вопрос или проблема

На 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, происходит следующее:

  1. Когда вы импортируете dash из routes.py в __init__.py, вы создаете сам Blueprint, но маршруты, определенные в views.py, не связываются с этим Blueprint. Это происходит потому, что ваш views.py фактически не выполняется до тех пор, пока приложение не будет выполнено, и обработчики маршрутов не будут добавлены к Blueprint.

  2. В результате, когда вы вызываете 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 необходимо тщательно контролировать. Если вы сталкиваетесь с проблемами регистрации маршрутов, всегда проверяйте, что все необходимые компоненты загружены до выполнения регистрации. Надеюсь, это поможет решить проблему! Если у вас есть дополнительные вопросы, не стесняйтесь задавать.

Оцените материал
Добавить комментарий

Капча загружается...