SQLAlchemy模型循环导入

时间:2015-12-22 17:18:38

标签: python sqlalchemy

我在同一模块中有两个名为models的模型。它们是1-1关系,并且已根据SQLAlchemy docs进行配置。

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 the <class 'models.AssetSetting.AssetSetting'> class after both dependent classes have been defined.

如果我使用类映射,我会得到经典的循环导入错误:

Traceback (most recent call last):
File "tracking_data_runner.py", line 7, in <module>
from models.Tracker import Tracker
File "/.../models/Tracker.py", line 5, in <module>
from models.Vehicle import Vehicle
File "/.../models/Vehicle.py", line 13, in <module>
from models.Tracker import Tracker
ImportError: cannot import name 'Tracker'

我相信我可以通过将文件放在同一个包中来解决这个问题,但我更愿意将它们分开。想法?

3 个答案:

答案 0 :(得分:10)

我发现我的问题有两个问题:

  1. 我在我的关系中不恰当地引用了relationship('Vehicle'。它应该是relationship('vehicles'而不是foreign_keys=Column(ForeignKey('vehicles.vehicle_id'))
  2. 显然在关系中声明FK是不合适的,就像我在 AssetSettings.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')) )中所做的那样。我必须申报FK,然后将其传递给关系。
  3. 我的配置现在看起来像这样:

    <强> Vehicle.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)
    

    <强> AssetSetting.py

    docker daemon -H 0.0.0.0:2376
    

答案 1 :(得分:9)

为避免循环导入错误,您应该使用字符串关系构建,但您的两个模型都必须使用相同的Base - 相同的{{ 1}}实例。实例化declarative_base一次,并在初始化BaseVehicle时使用它。

或者,您可以显式映射表名和类,以帮助映射器关联您的模型:

AssetSetting

答案 2 :(得分:3)

您的__tablename__引用了vehicles,但您的外键引用了vehicle.vehicle_id