Reputation: 1160
Let say I have two tables
Order table
class Order(db.Model):
id = db.Column(db.Integer, primary_key=True)
deliveries = db.relationship("Delivery", back_populates="order")
Delivery table
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")
One order may have many deliveries. The status field of delivery table has following possible values ["Planned", "Failed", "Delivered"]
Question: How can make sure that one order does not have two planned deliveries ?
Tips: I know I can implemt unique constraint on multiple tables like adding below line to delivery schema
__table_args__ = (db.UniqueConstraint('order_id', 'status', name='_order_status_uc'))
But by doing so I will prevent one order from having two failed deliveries.
Any help will be greatly appreciate as I want to enforce this constraint directly in the db.
Upvotes: 1
Views: 1508
Reputation: 76992
Update (given it is PostgreSQL)
Given you use PostgreSQL, the most straightforward solution is to use Partial Unique Index:
CREATE UNIQUE INDEX _order_status_uc ON delivery (order_id) WHERE status = 'Planned';
If you use SQLAlchemy to create the index, the below should be equivalent:
class Delivery(Base): # ...
__table_args__ = (
Index(
'_order_status_uc',
'order_id',
unique=True,
postgresql_where=(status == 'Planned'),
),
)
Original answer
Assuming the RDBMS you are using supports this, one implementation idea would be to do as follows:
delivery
table which would have value of order_id
for "Planned" status
and NULL
otherwiseUNIQUE Constraint
on this computed column.This assumes the following regarding used RDBMS:
NULL
values are allowed.Please see PostgreSQL unique constraint null: Allowing only one Null article for more background.
Upvotes: 2
Reputation: 880
You could query your delivery model with the current order id and status planned, if there is a result, raise validation.
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
Upvotes: 0