Ответ 1
В настоящее время вы настроили свое приложение, используя приблизительный эквивалент шаблона Application Factory (так называемый документация к фляге). Это идея Flask, а не Python. Он имеет некоторые преимущества, но это также означает, что вам нужно делать такие вещи, как инициализировать объект SQLAlchemy, используя метод init_app
, а не конструктор SQLAlchemy. Нет ничего "неправильного" в том, чтобы делать это таким образом, но это означает, что вам нужно запустить такие методы, как create_all()
в контексте , который в настоящее время вы бы этого не сделали, если бы попытались запустить его в методе main()
.
Есть несколько способов разрешить это, но вам решать, какой из них вы хотите (нет правильного ответа):
Не используйте шаблон приложения Factory
Таким образом, вы не создаете приложение в функции. Вместо этого вы помещаете его где-нибудь (например, в project/__init__.py
). Ваш файл project/__init__.py
может импортировать пакет models
, а пакет models
может импортировать app
из project
. Это круговая ссылка, но это нормально, пока объект app
создается в пакете project
, прежде чем model
попытается импортировать app
из package
. См. Документы Flask в Более крупные шаблоны приложений для примера, где вы можете разделить свой пакет на несколько пакетов, но все же у вас есть возможность использовать эти другие пакеты объект app
, используя круговые ссылки. Документы даже говорят:
Каждый программист на Python ненавидит их, и все же мы просто добавили некоторые из них: круглый импорт. [...] Имейте в виду, что это плохая идея вообще, но здесь она действительно прекрасна.
Если вы это сделаете, вы можете изменить свой файл Models/__init__.py
для создания объекта SQLAlchemy
со ссылкой на приложение в конструкторе. Таким образом, вы можете использовать методы create_all()
и drop_all()
объекта SQLAlchemy
, как описано в документации по Flask-SQLAlchemy.
Сохраните его, но создайте в request_context()
Если вы продолжаете то, что у вас есть (создание вашего приложения в функции), вам нужно будет создать объект SQLAlchemy
в пакете models
, не используя объект app
как часть конструктора ( как вы это сделали). В своем основном методе измените...
db = SQLAlchemy(app)
... до...
db.init_app(app)
Затем вам нужно переместить метод create_all()
в функцию внутри контекста приложения. Обычный способ сделать это для чего-то, что на ранней стадии проекта будет заключаться в использовании before_first_request()
decorator....
app = Flask(...)
@app.before_first_request
def initialize_database():
db.create_all()
Метод "initialize_database" запускается до того, как первый запрос обрабатывается Flask. Вы также можете сделать это в любой момент, используя метод app_context()
:
app = Flask(...)
with app.app_context():
# This should work because we are in an app context.
db.create_all()
Поймите, что если вы собираетесь продолжать использовать шаблон Application Factory, вы должны действительно понять, как работает контекст приложения; это может сбивать с толку сначала, но необходимо понять, какие ошибки, такие как "приложение, не зарегистрированное на экземпляре db и не связанное с текущим контекстом", означают.