2017-09-29 38 views
0

我嘗試刪除數據,但SQLAlchemy的試圖做兩次,並回滾 基地PostgreSQL的 9.6版 SQLAlchemy的1.0.14 psycopg2 2.7.3.1SQLAlchemy的許多一對多PostgreSQL的雙刪除

class IdentifiedObject(Base): 
    __tablename__ = 'identifiedobject' 
    mRID = Column(UUID, server_default=sqlalchemy.text("uuid_generate_v4()"), primary_key=True) 
    name = Column(String) 
    polymorphic_type = Column(String, nullable=False) 
    __mapper_args__={'polymorphic_identity':__tablename__,'polymorphic_on':polymorphic_type} 
assoc_1 = Table("assoc_1", Base.metadata, 
    Column("cars_mRID", None, ForeignKey("cars.mRID")), 
    Column("games_mRID", None, ForeignKey("games.mRID"))) 
class Cars(IdentifiedObject): 
    __tablename__='cars' 
    mRID = Column(None, ForeignKey('identifiedobject.mRID'), primary_key=True) 
    polymorphic_type = Column(String, nullable=False) 
    __mapper_args__={'polymorphic_identity':__tablename__,'inherit_condition': mRID == IdentifiedObject.mRID,'polymorphic_on':polymorphic_type} 
    status = Column(String) 
    Games = relationship("Games", secondary = "assoc_1", back_populates="Cars", primaryjoin="(cars.c.mRID==assoc_1.c.cars_mRID)") 
class Games(IdentifiedObject): 
    __tablename__='games' 
    mRID = Column(None, ForeignKey('identifiedobject.mRID'), primary_key=True) 
    polymorphic_type = Column(String, nullable=False) 
    __mapper_args__={'polymorphic_identity':__tablename__,'inherit_condition': mRID == IdentifiedObject.mRID,'polymorphic_on':polymorphic_type} 
    status = Column(String) 
    Cars = relationship("Cars", secondary = "assoc_1", back_populates="Games", primaryjoin="(games.c.mRID==assoc_1.c.games_mRID)") 

Base.metadata.create_all(engine) 
Base.prepare(engine, reflect=True) 
session = Session(bind=engine) 
session.add(IdentifiedObject()) 
games=Games(Cars=[Cars(),Cars()]) 
session.add (games) 
session.commit() 
session.close() 
session.delete(games) 
session.commit() 

現在,我們發現了一個異常

2017-09-29 09:17:44,996 INFO sqlalchemy.engine.base.Engine SELECT cars."mRID" AS "cars_mRID", identifiedobject."mRID" AS "identifiedobject_mRID", identifiedobject.name AS identifiedobject_name, cars.polymorphic_type AS cars_polymorphic_type, identifiedobject.polymorphic_type AS identifiedobject_polymorphic_type, cars.status AS cars_status 
FROM assoc_1, identifiedobject JOIN cars ON cars."mRID" = identifiedobject."mRID" 
WHERE %(param_1)s = assoc_1."games_mRID" AND cars."mRID" = assoc_1."cars_mRID" 
2017-09-29 09:17:44,996 INFO sqlalchemy.engine.base.Engine {'param_1': UUID('7a960989-5e3e-45dc-87c1-1b62ffa3694a')} 
2017-09-29 09:17:44,997 INFO sqlalchemy.engine.base.Engine DELETE FROM assoc_1 WHERE assoc_1."cars_mRID" = %(cars_mRID)s AND assoc_1."games_mRID" = %(games_mRID)s 
2017-09-29 09:17:44,998 INFO sqlalchemy.engine.base.Engine ({'games_mRID': UUID('7a960989-5e3e-45dc-87c1-1b62ffa3694a'), 'cars_mRID': UUID('a3135561-e416-45c0-b9f8-aead59ef6b34')}, {'games_mRID': UUID('7a960989-5e3e-45dc-87c1-1b62ffa3694a'), 'cars_mRID': UUID('b77b9dc4-65da-45ea-be52-dc53e2bcd74b')}) 
2017-09-29 09:17:44,998 INFO sqlalchemy.engine.base.Engine DELETE FROM assoc_1 WHERE assoc_1."cars_mRID" = %(cars_mRID)s AND assoc_1."games_mRID" = %(games_mRID)s 
2017-09-29 09:17:44,999 INFO sqlalchemy.engine.base.Engine ({'games_mRID': UUID('7a960989-5e3e-45dc-87c1-1b62ffa3694a'), 'cars_mRID': UUID('a3135561-e416-45c0-b9f8-aead59ef6b34')}, {'games_mRID': UUID('7a960989-5e3e-45dc-87c1-1b62ffa3694a'), 'cars_mRID': UUID('b77b9dc4-65da-45ea-be52-dc53e2bcd74b')}) 
2017-09-29 09:17:44,999 INFO sqlalchemy.engine.base.Engine ROLLBACK 
Traceback (most recent call last): 
    File "testing.py", line 98, in <module> 
    session.commit() 

異常數據

sqlalchemy.orm.exc.StaleDataError: DELETE statement on table 'assoc_1' expected to delete 2 row(s); Only 0 were matched. 

還沒有在其他答案中找到

回答

0

這是由specifying parts of the Declarative classes explicitly手動引起的,並使用automapper對現有表格造成的。的關係,你手動定義不使用由automapper使用的默認命名約定,所以它創造的關係的另一個版本:

In [8]: list(inspect(Games).relationships) 
Out[8]: 
[<RelationshipProperty at 0x7f932dea8ac8; Cars>, 
<RelationshipProperty at 0x7f932de6c2c8; cars_collection>] 

所以,當你發出的刪除,兩者的關係解僱他們瀑布,你會得到2 DELETE語句。壓倒一切的關係在文檔特別提醒:

以上,更復雜的細節之一是,我們闡述了覆蓋該自動映射可能已經被創建relationship()對象之一。要做到這一點,我們需要確保的名稱相匹配了什麼自動地圖通常會產生,在這種關係的名稱將是User.address_collection ......

爲了解決這個問題要麼恢復使用默認的命名方案,或provide your own

In [6]: def class_name_collection(base, local_cls, referred_cls, constraint): 
    ...:  return referred_cls.__name__ 
    ...: 

然後

...: Base.prepare(engine, reflect=True, 
    ...:    name_for_collection_relationship=class_name_collection) 
+0

謝謝,它的作品! –

+0

對不起,我只對原型使用autobase。在declare_base我沒有使用準備功能。它是否適用於聲明基礎? –

+0

因爲它不會自動生成關係,所以不會用「簡單」聲明來運行。 –

相關問題