Я установил экземпляр базы данных, используемый многими моделями:
Database.py:
from flask_sqlalchemy import SQLAlchemy
from models.shared import load_db
def init_db(app):
db = SQLAlchemy(app)
load_db(db)
from models.user import User
from models.another_model import AnotherModel
from ...
init_db вызывается из create_app в моем основном файле server.py.
Shared.py:
db = None
def load_db(_db):
db = _db
print(db)
User.py:
from .shared import db
print("User model defined.")
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(15), unique=True, nullable=False)
hash = db.Column(db.String(32), nullable=False)
email = db.Column(db.String(100), unique=True, nullable=False)
def __repr__(self):
return '<User %r>' % self.username
Когда init_db вызывается из метода create_app в моем основном файле, я получаю:
AttributeError: 'NoneType' object has no attribute 'Model'
Почему я получаю эту ошибку? При импорте модулей модели изнутри init_db не должен ли их код запускаться после того, как я вызываю load_db? Если посмотреть на порядок операторов печати, db явно установлен до того, как его будет использовать какая-либо модель:
<SQLAlchemy engine=mysql://root:***@localhost/db_name?charset=utf8>
User model defined.






В
def load_db(_db):
db = _db
print(db)
Фактически вы объявляете переменную db локальной для функции load_db.
Чтобы действительно сослаться на глобальную переменную db, попробуйте выражение global db:
def load_db(_db):
global db
db = _db
print(db)
Я считаю этот код довольно ненадежным, но я бы подумал об использовании синглтонов или другого подхода.
Рассмотрим случай, когда вы импортировали dbперед, он был инициализирован. Нравиться:
from .shared import db
save_for_later_use(db)
Даже если вы замените db в модуле shared, shared.db будет указывать на инициализированное значение, в то время как у вас будет неинициализированное значение, уже указанное переменной, которую вы сохранили где-то в save_for_later_use.
Другими словами, вы повторили то, на что указывает shared.db, но какой бы код ни пытался запомнить shared.db до инициализации, все равно будет содержать указатель на None.