python - 跨多个文件的烧瓶 sqlalchemy 关系
问题描述
我是 Flask Sqlalchemy 的新手,我想声明多个模型并将它们相互关联,我按照文档中的示例进行操作,但我不断收到此错误
sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Organization->organizations,
expression 'User' failed to locate a name ('User').
If this is a class name,
consider adding this relationship()
to the <class 'models.Organization.Organization'>
class after both dependent classes have been defined
我不想将所有模型存储在一个文件中,因为随着时间的推移项目可能会变得越来越大,所以我创建了以下结构:
- models
--- __init__.py
--- User.py
--- Organization.py
--- ...
- manage.py
- app.py
我希望用户属于一个组织,并且该组织有很多用户,我也希望该组织为自己的反身关系提供一个可选字段,这是我尝试过的。
初始化.py
from .Attachment import Attachment
from .Invoice import Invoice
from .Organization import Organization
from .Setting import Setting
from .Transaction import Transaction
from .User import User
用户.py
from app import db, ma
from marshmallow_enum import EnumField
import enum
import bcrypt
class RuleEnum(enum.Enum):
admin = 'admin',
collector = 'collector'
retailer = 'retailer'
vendor = 'vendor'
vendor_admin = 'vendor_admin'
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False)
mobile = db.Column(db.String(), nullable=False)
username = db.Column(db.String(), unique=True, nullable=False)
password = db.Column(db.TEXT(), nullable=False)
is_active = db.Column(db.Boolean(), default=False)
rule = db.Column(db.Enum(RuleEnum), nullable=False)
created_on = db.Column(db.DateTime, server_default=db.func.now())
updated_on = db.Column(db.DateTime, server_default=db.func.now(), server_onupdate=db.func.now())
# relations
#related fields
organization_id = db.Column(db.Integer, db.ForeignKey('organizations.id'), nullable=True)
def __init__(
self,
name,
username,
mobile,
password,
rule,
is_active,
organization_id = None
):
self.name = name
self.username = username
self.mobile = mobile
self.rule = rule
self.is_active = is_active
self.organization_id = organization_id
self.password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode()
def __repr__(self):
return "<id %s>" % self.id
class UserSchema(ma.SQLAlchemyAutoSchema):
rule = EnumField(RuleEnum, by_value=True)
class Meta:
exclude = ['password']
model = User
load_instance = True
组织.py
from app import db, ma
import enum
from marshmallow_enum import EnumField
class TypeEnum(enum.Enum):
vendor = 'vendor'
retailer = 'retailer'
class Organization(db.Model):
__tablename__ = 'organizations'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String())
cr = db.Column(db.String(), unique=True)
location = db.Column(db.String())
is_request_approved = db.Column(db.Boolean(), default=False)
is_active = db.Column(db.Boolean(), default=False)
type = db.Column(db.Enum(TypeEnum))
created_on = db.Column(db.DateTime, server_default=db.func.now())
updated_on = db.Column(db.DateTime, server_default=db.func.now(), server_onupdate=db.func.now())
# relations
# virtual columns
parent = db.relationship('Organization', remote_side=id, backref='sub_organizations')
users = db.relationship('User', backref='organization')
# related fields
parent_id = db.Column(db.Integer, db.ForeignKey('organizations.id'), nullable=True)
def __init__(
self,
name,
cr,
location,
is_request_approved,
is_active,
type,
parent_id = None
):
self.name = name
self.cr = cr
self.location = location
self.is_request_approved = is_request_approved
self.is_active = is_active
self.type = type
self.parent_id = parent_id
def __repr__(self):
return "<id %s>" % self.id
class OrganizationSchema(ma.SQLAlchemyAutoSchema):
type = EnumField(TypeEnum, by_value=True)
class Meta:
model = Organization
load_instance = True
关于迁移,我关注了一篇博客文章并manage.py
使用此代码制作了文件
管理.py
import os
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import app, db
app.config.from_object(os.environ['APP_SETTINGS'])
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
解决方案
为了将来参考,我通过在我的__init__.py
文件中安排导入语句来解决它,以便在关系中可能引用的任何类都应该在之前导入,所以在我的情况下,我不得不将__init__.py
文件更改为以下
from .User import User # User class is imported before it's referenced in the Organization model
from .Attachment import Attachment
from .Invoice import Invoice
from .Organization import Organization
from .Setting import Setting
from .Transaction import Transaction
这不是理想的解决方案,我确信有更好的方法,因此欢迎任何其他/更好的方法供将来参考。
推荐阅读
- angular - 找不到在 Angular 8 组件中返回对象数组的方法
- powershell - 用于检索第二个模式值的 Powershell 命令
- ios - 有时会出现错误,否则工作正常,如何确保消除错误?
- java - 访问由已实现接口引用的枚举的注释
- swiftui - SwiftUI 获取某些视图的 EnvironmentValues,仅给出对视图的引用
- scala - 仅为类标记参数实现函子映射
- elasticsearch - elasticsearch6.4.3中如何设置集群重启优雅并控制分片分配方式
- png - 如何调整PNG文件的大小?
- javascript - 如何从数组中的数组的第一个元素创建新数组
- python - ldap3 连接绑定后返回错误代码