Flask 对具有给定值的多个列的唯一约束

Flask 对具有给定值的多个列的唯一约束,flask,sqlalchemy,flask-sqlalchemy,Flask,Sqlalchemy,Flask Sqlalchemy,假设我有两张桌子 订单表 class Order(db.Model): id = db.Column(db.Integer, primary_key=True) deliveries = db.relationship("Delivery", back_populates="order") 交货台 class Delivery(db.Model): id = db.Column(db.Integer, primary_key=True)

假设我有两张桌子

订单表

class Order(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  deliveries = db.relationship("Delivery", back_populates="order")
交货台

class Delivery(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  status= db.Column(db.String(20))
  order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False)
  order = db.relationship("Order", back_populates="deliveries")
一个订单可能有多个交货。交货表的状态字段具有以下可能值
[“计划”、“失败”、“已交货”]

问题: 如何确保一个订单没有两次计划交货

提示: 我知道我可以在多个表上实施唯一约束,比如在交付模式中添加下线

\uuuu表参数(db.UniqueConstraint('order\u id','status',name=''u order\u status\u uc'))

但通过这样做,我将防止一个订单出现两次交付失败


非常感谢您提供的任何帮助,因为我希望直接在数据库中实施此约束。

您可以使用当前订单id和计划状态查询您的交货模型,如果有结果,请进行验证

planned_delivery_exist_boolean = db.session.query(Delivery).filter(Delivery.order_id==order_id).filter(Delivery.status=="Planned").first()

if planned_delivery_exist_boolean:
    # trigger validation error

更新(假定为PostgreSQL)

如果您使用PostgreSQL,最简单的解决方案是:

创建唯一索引_order_status_uc ON delivery(order_id),其中status='Planned'

如果使用SQLAlchemy创建索引,则以下内容应等效:

课程交付(基本): #

原始答案

假设您使用的RDBMS支持这一点,一种实现思想是如下所示:

  • delivery
    表上创建一个计算列,该列的“计划”
    状态的值为
    order\u id
    ,否则为
    NULL
  • 在此计算列上创建一个
    唯一约束
这假设了以下关于所用RDBMS的情况:

  • 计算列不仅受支持,而且可以是索引/约束的一部分
  • 唯一索引的实现允许多个
    NULL

  • 请参阅文章了解更多背景。

    您正在使用的数据库引擎是什么?我正在使用PostgreSQL我相信有人会想到一个约束更宽松的解决方案。如果使用PostgreSQL,则在订单id上使用状态为“计划”的部分唯一索引。
    ?我打赌这就是为什么您已经询问了DBMS。到目前为止,我没有找到一个非常适合的约束实现。这个提议是一个变通办法,我接受了。非常感谢@vanThis只能在ORM级别工作。我想要一些关于数据库级别的东西,这是我为什么要寻找db约束的原因
    __table_args__ = (
        Index(
            '_order_status_uc',
            'order_id',
            unique=True,
            postgresql_where=(status == 'Planned'),
        ),
    )