(flask)-sqlalchemy查询,必须导入所有模型
(flask)-sqlalchemy query, have to import all models
我在使用 Flask 和 Flask-SQLAlchemy 时遇到问题,对于任何查询,我都需要导入所有相关模型。
现在我的 auth.views.py 看起来像这样(编程的前几行只是一个测试视图)
from flask import jsonify
from . import auth
from app.models.user import User
@auth.route('/', methods=['GET'])
def index():
users = User.query.all()
return jsonify({'name': users[0].name})
现在我收到一个错误
"InvalidRequestError: When initializing mapper Mapper|User|user, expression 'Course' failed to locate a name ("name 'Course' is not defined"). 如果这是一个 class 名字,考虑在 both dependent classes 已被定义。"
我有一个项目,其中有一个像这样的模型包
app
├── auth
│ ├── __init__.py
│ └── views.py
├── __init__.py
└── models
├── assignment.py
├── base.py
├── client.py
├── course.py
├── __init__.py
├── submission.py
└── user.py
我的用户 class 有一个多对多的课程和一个一对多的提交。
这是通过导入课程解决的(然后是提交,然后是那里的关系,最终基本上是所有模型。)
在为 Pyramid 项目工作时,我们也使用 SQLAlchemy,但我从来不需要导入所有模型来完成我的工作。有什么想法吗?我真的想不通,我也没能google。
用户看起来像这样
user_course = db.Table(
'user_course', db.Model.metadata,
db.Column('student_id', UUID, db.ForeignKey('user.id'),
primary_key=True),
db.Column('course_id', UUID, db.ForeignKey('course.id'),
primary_key=True)
)
class User(db.Model):
id = db.Column(UUID, default=lambda: str(uuid.uuid4()), primary_key=True)
firstname = db.Column(db.String(100), nullable=False)
lastname = db.Column(db.String(100), nullable=False)
insertion = db.Column(db.String(15)) # tussenvoegsel
# email = db.Column(db.String, nullable=False, unique=True)
password_hash = db.Column(db.String, nullable=False)
enrolled_courses = db.relationship('Course', secondary=user_course,
backref='students')
managed_courses = db.relationship('Course', backref='teacher')
submissions = db.relationship('Submission', backref='student')
@property
def name(self):
return "{}{}{}".format(
self.firstname + " ",
self.insertion + " " if self.insertion else "",
self.lastname
)
@property
def password(self):
raise AttributeError("Password is not a readable attribute")
@password.setter
def password(self, password):
self.password_hash = bcrypt.hashpw(password, bcrypt.gensalt(12))
def verify_password(self, password):
return bcrypt.hashpw(password, self.password_hash) == \
self.password_hash
好吧,很明显你无法绕过加载所有模块。我不想手动执行此操作,所以我在 __init__.py
中求助于此。现在所有的模块都将像注释所说的那样执行。
import inspect
import pkgutil
import importlib
import sys
def import_models():
thismodule = sys.modules[__name__]
for loader, module_name, is_pkg in pkgutil.iter_modules(
thismodule.__path__, thismodule.__name__ + '.'):
module = importlib.import_module(module_name, loader.path)
for name, _object in inspect.getmembers(module, inspect.isclass):
globals()[name] = _object
import_models()
如果你真的想坚持一个文件一个 class 方案,在我看来,更清晰的选择是在模型包的初始化中进行导入:
models/__init__.py:
from user import User
from client import Client
from course import Course
# plus your remaining classes
然后您可以将 classes 导入为
from models import User
这使事情更具可读性,并允许将每个 class 一个文件的方案与包含多个 classes 的模块混合,同时仍然能够导入所有 class 以 "flat" 的方式来自 models
。
我在使用 Flask 和 Flask-SQLAlchemy 时遇到问题,对于任何查询,我都需要导入所有相关模型。
现在我的 auth.views.py 看起来像这样(编程的前几行只是一个测试视图)
from flask import jsonify
from . import auth
from app.models.user import User
@auth.route('/', methods=['GET'])
def index():
users = User.query.all()
return jsonify({'name': users[0].name})
现在我收到一个错误
"InvalidRequestError: When initializing mapper Mapper|User|user, expression 'Course' failed to locate a name ("name 'Course' is not defined"). 如果这是一个 class 名字,考虑在 both dependent classes 已被定义。"
我有一个项目,其中有一个像这样的模型包
app
├── auth
│ ├── __init__.py
│ └── views.py
├── __init__.py
└── models
├── assignment.py
├── base.py
├── client.py
├── course.py
├── __init__.py
├── submission.py
└── user.py
我的用户 class 有一个多对多的课程和一个一对多的提交。
这是通过导入课程解决的(然后是提交,然后是那里的关系,最终基本上是所有模型。)
在为 Pyramid 项目工作时,我们也使用 SQLAlchemy,但我从来不需要导入所有模型来完成我的工作。有什么想法吗?我真的想不通,我也没能google。
用户看起来像这样
user_course = db.Table(
'user_course', db.Model.metadata,
db.Column('student_id', UUID, db.ForeignKey('user.id'),
primary_key=True),
db.Column('course_id', UUID, db.ForeignKey('course.id'),
primary_key=True)
)
class User(db.Model):
id = db.Column(UUID, default=lambda: str(uuid.uuid4()), primary_key=True)
firstname = db.Column(db.String(100), nullable=False)
lastname = db.Column(db.String(100), nullable=False)
insertion = db.Column(db.String(15)) # tussenvoegsel
# email = db.Column(db.String, nullable=False, unique=True)
password_hash = db.Column(db.String, nullable=False)
enrolled_courses = db.relationship('Course', secondary=user_course,
backref='students')
managed_courses = db.relationship('Course', backref='teacher')
submissions = db.relationship('Submission', backref='student')
@property
def name(self):
return "{}{}{}".format(
self.firstname + " ",
self.insertion + " " if self.insertion else "",
self.lastname
)
@property
def password(self):
raise AttributeError("Password is not a readable attribute")
@password.setter
def password(self, password):
self.password_hash = bcrypt.hashpw(password, bcrypt.gensalt(12))
def verify_password(self, password):
return bcrypt.hashpw(password, self.password_hash) == \
self.password_hash
好吧,很明显你无法绕过加载所有模块。我不想手动执行此操作,所以我在 __init__.py
中求助于此。现在所有的模块都将像注释所说的那样执行。
import inspect
import pkgutil
import importlib
import sys
def import_models():
thismodule = sys.modules[__name__]
for loader, module_name, is_pkg in pkgutil.iter_modules(
thismodule.__path__, thismodule.__name__ + '.'):
module = importlib.import_module(module_name, loader.path)
for name, _object in inspect.getmembers(module, inspect.isclass):
globals()[name] = _object
import_models()
如果你真的想坚持一个文件一个 class 方案,在我看来,更清晰的选择是在模型包的初始化中进行导入:
models/__init__.py:
from user import User
from client import Client
from course import Course
# plus your remaining classes
然后您可以将 classes 导入为
from models import User
这使事情更具可读性,并允许将每个 class 一个文件的方案与包含多个 classes 的模块混合,同时仍然能够导入所有 class 以 "flat" 的方式来自 models
。