我在同一个模块中有两个模型models
.它们是1-1关系,并且已根据SQLAlchemy文档进行配置.
Vehicle.py
from models.AssetSetting import AssetSetting class Vehicle(Base): __tablename__ = 'vehicles' vehicle_id = Column(Integer, primary_key=True) ... settings = relationship('AssetSetting', backref=backref('asset_settings'))
AssetSetting.py
from models.Vehicle import Vehicle class AssetSetting(Base): __tablename__ = 'asset_settings' asset_alert_setting_id = Column(Integer, primary_key=True, autoincrement=True) ... vehicle = relationship('vehicles', foreign_keys=Column(ForeignKey('vehicles.vehicle_id')))
如果我使用字符串关系构建(即ForeignKey('vehicles.vehicle_id')
)我得到错误:
sqlalchemy.exc.InvalidRequestError: When initializing mapper Mapper|AssetSetting|asset_settings, expression 'vehicles' failed to locate a name ("name 'vehicles' is not defined"). If this is a class name, consider adding this relationship() to theclass after both dependent classes have been defined.
如果我使用类映射,我会得到经典的循环导入错误:
Traceback (most recent call last): File "tracking_data_runner.py", line 7, infrom models.Tracker import Tracker File "/.../models/Tracker.py", line 5, in from models.Vehicle import Vehicle File "/.../models/Vehicle.py", line 13, in from models.Tracker import Tracker ImportError: cannot import name 'Tracker'
我相信我可以通过将文件放在同一个包中来解决这个问题,但我更愿意将它们分开.思考?
为了避免循环导入错误,您应该使用字符串关系构建,但是两个模型都必须使用Base
相同的declarative_base
实例.实例化Base
一次初始化时都用它Vehicle
和AssetSetting
.
或者,您可以显式映射表名和类,以帮助映射器关联您的模型:
Base = declarative_base(class_registry={"vehicles": Vehicle, "asset_settings": AssetSetting})
我发现我的问题有两个问题:
我Vehicles
在我的关系中不恰当地引用.应该relationship('Vehicle'
不是relationship('vehicles'
显然,就像在AssetSettings.py(foreign_keys=Column(ForeignKey('vehicles.vehicle_id'))
)中那样在关系中声明FK是不合适的.我必须声明FK,然后将其传递给关系.
我的配置现在看起来像这样:
Vehicle.py
class Vehicle(Base, IDiagnostable, IUsage, ITrackable): __tablename__ = 'vehicles' vehicle_id = Column(Integer, primary_key=True)_id = Column(Integer) settings = relationship('AssetSetting', backref=backref('asset_settings'))
AssetSetting.py
class AssetSetting(Base): __tablename__ = 'asset_settings' asset_alert_setting_id = Column(Integer, primary_key=True, autoincrement=True) vehicle_id = Column(ForeignKey('vehicles.vehicle_id')) vehicle = relationship('Vehicle', foreign_keys=vehicle_id)