Python / SqlAlchemy 3路循环依赖

时间:2014-07-02 15:06:32

标签: python sqlalchemy circular-dependency

我遇到了在我的3个表中创建一组关系的问题。当我运行代码来创建表时,我得到循环依赖性错误。

我根据对类似帖子的回复尝试摆弄use_alterpost_update,但我无法解决问题。

基本上地图有一组位置,一个角色有一组地图,但是一个角色也位于其中一个地图位置上。 此外,地图可以与其他地图建立父/子关系。

class Character(Base):
    __tablename__ = 'character'

    ID = Column(Integer, primary_key=True)
    name = Column(Unicode(255), nullable=False)
    classID = Column(Integer, nullable=False)
    created = Column(DateTime, nullable=False, default=datetime.datetime.utcnow)

    profileID = Column(Integer, ForeignKey('profile.ID'), nullable=False)
    locationID = Column(Integer, ForeignKey('location.ID'))

    location = relationship("Location")
    maps = relationship("Map", backref="owner", cascade="save-update, merge, delete, delete-orphan")

class Map(Base):
    __tablename__ = 'map'

    ID = Column(Integer, primary_key=True)
    name = Column(Unicode(255))
    maptypeID = Column(Integer, nullable=False)
    created = Column(DateTime, nullable=False, default=datetime.datetime.utcnow)

    parentID = Column(Integer, ForeignKey('map.ID'))
    ownerID = Column(Integer, ForeignKey('character.ID'))

    children = relationship("Map", backref=backref("parent", remote_side="Map.ID"))
    locations = relationship("Location", backref='map', cascade="save-update, merge, delete, delete-orphan")

class Location(Base):
    __tablename__ = 'location'

    ID = Column(Integer, primary_key=True)
    x = Column(Integer, nullable=False)
    y = Column(Integer, nullable=False)
    locationtypeID = Column(Integer, nullable=False)
    created = Column(DateTime, nullable=False, default=datetime.datetime.utcnow)

    mapID = Column(Integer, ForeignKey('map.ID'), nullable=False)

我该如何解决这个问题?

修改(已解决):

在更多地使用use_alter后,我能够通过更改Location类中的mapID定义来解决问题:

mapID = Column(Integer, ForeignKey('map.ID'), nullable=False)

要:

mapID = Column(Integer, ForeignKey('map.ID', use_alter=True, name="fk_location_map"), nullable=False)

响应打破循环依赖的建议,我宁愿在模式中表示正确的关系和数据完整性。我非常担心修复ORM问题或更改ORM而不是捏造架构以符合ORM的期望。

在这种特殊情况下,我无法想出一种更简洁,更优雅的方式来表示我需要模式的所有信息(在最基本的意义上)代表申请。

旁注:与其他语言/框架/ ORM合作后,ORM通常会自动解决这种问题。例如,在.NET E / F中,我相信通常会在所有表创建语句之后添加和激活FK约束。

1 个答案:

答案 0 :(得分:0)

您可以使用alembic来帮助您在架构中使用循环依赖,但我不会帮助您。相反,我强烈要求你打破循环依赖

如果我了解您的架构,您的模型中的房间或建筑物由Location代表。您的架构中的玩家/怪物是Character s,它们在任何时候都必须只有一个location。此外,还有一些Map个项目浮动,总是某些特定location,并且总是在一个character的库存中。

所以我在这里拼写

class Location:
    id = Column(Integer, primary_key=True)

class Character:
    id = Column(Integer, primary_key=True)
    location_id = Column(ForeignKey(Location.id))

    location = relationship(Location, backref="characters")

class Map:
    id = Column(Integer, primary_key=True)
    location_id = Column(ForeignKey(Location.id))
    owner_id = Column(ForeignKey(Character.id))

    location = relationship(Location, backref="maps")
    owner = relationship(Character, backref="inventory")