繁体   English   中英

FastAPI SQLAlchemy 删除多对多关系导致 StaleDataError

[英]FastAPI SQLAlchemy delete Many-to-Many relation causes StaleDataError

从表中删除 ManyToMany 关系时出错。 我发现问题是由bills_dishes表中的相同项目引起的,但我需要添加相同的项目。

因此,下面的代码适用于没有重复项的项目,例如:

bill_id | dish_id
1       | 1
1       | 2

楷模:

bills_dishes_association = Table(
    "bills_dishes",
    Base.metadata,
    Column("bill_id", Integer, ForeignKey("bills.id")),
    Column("dish_id", Integer, ForeignKey("dishes.id")),
)


class Waiter(Base):
    """Waiter model."""

    __tablename__ = "waiters"

    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    password = Column(String(6), nullable=False)
    bills = relationship("Bill")

    def __repr__(self):
        return f"Waiter(id={self.id}, username={self.username})"


class Bill(Base):
    """Bill model."""

    __tablename__ = "bills"

    id = Column(Integer, primary_key=True, autoincrement=True)
    waiter_id = Column(Integer, ForeignKey("waiters.id"), nullable=False)
    table_number = Column(Integer, nullable=False)
    amount = Column(Float, nullable=False)
    tip_percent = Column(Integer)
    tip_included = Column(Boolean, default=False, nullable=False)
    time = Column(DateTime(timezone=True), server_default=func.now())

    dishes = relationship(
        "Dish", secondary=bills_dishes_association, back_populates="ordered"
    )

    def __repr__(self):
        return f"Bill(id={self.id}, table_number={self.table_number}, amount={self.amount})"


class Dish(Base):
    """Dish model."""

    __tablename__ = "dishes"

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(100), nullable=False)
    description = Column(String(1024), nullable=False)
    image_url = Column(String(500), nullable=False)
    cost = Column(Float)

    ordered = relationship(
        "Bill",
        secondary=bills_dishes_association,
        back_populates="dishes",
        cascade="all, delete",
        passive_deletes=True,
    )

crud.py:

def delete_bill(db: Session, bill_id: int):
    """Delete a bill by id."""
    db_bill = db.query(Bill).filter(Bill.id == bill_id).first()
    db.delete(db_bill)
    db.commit()
    return db_bill

但它不适用于这种情况:

bill_id | dish_id
1       | 2
1       | 2

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

如何处理?

我认为您需要在Bill中的dishes关系上设置passive_deletes=True并将ondelete="CASCADE"添加到bills_dishes_association中的两个外键。

尽管对于关键表,您最好将 bills_dishes 提升为更像bills_dishes的东西,并将其提升为像bill_lines这样的完整的BillLine这样Bill -- 1tomany -- BillLine -- manyto1 -- Dish并给它自己的 PK id:

sqlalchemy.orm.relationship.params.passive_deletes

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM