fix(itinerary): suppress false-positive UniqueTogetherValidator in CollectionItineraryItemSerializer (#1157)

DRF 3.15 inspects `UniqueConstraint` entries from `Model._meta.constraints`
and auto-generates `UniqueTogetherValidator` objects for them, but strips
each constraint's `condition` argument in the process.

The `CollectionItineraryItem` model has two conditional constraints:
- `unique_order_per_collection_day`: unique `(collection, date, order)`
  only when `is_global=False AND date IS NOT NULL`
- `unique_order_per_collection_global`: unique `(collection, order)`
  only when `is_global=True`

Without their conditions, DRF turns the second constraint into a validator
that checks `(collection, order)` across *all* rows regardless of type.
This means adding any dated itinerary item (transportation, lodging, etc.)
with `order=0` is rejected with 400 whenever a trip-wide (global) item
already holds `order=0` for the same collection — which is almost always,
since global items start at order 0.

Fix: set `validators = []` on the serializer Meta to suppress the
incorrectly-stripped validators. The view already adjusts `order` to avoid
real conflicts within each group, and the DB-level constraints continue
to enforce conditional uniqueness correctly.

This actually fixes #1153 for me

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Maxim Burgerhout
2026-05-24 15:07:18 +02:00
committed by GitHub
parent eaa66d08fa
commit 8374d2a1f7

View File

@@ -1071,6 +1071,11 @@ class CollectionItineraryItemSerializer(CustomModelSerializer):
model = CollectionItineraryItem
fields = ['id', 'collection', 'content_type', 'object_id', 'item', 'date', 'is_global', 'order', 'start_datetime', 'end_datetime', 'created_at', 'object_name']
read_only_fields = ['id', 'created_at', 'start_datetime', 'end_datetime', 'item', 'object_name']
# DRF 3.15 generates UniqueTogetherValidator from UniqueConstraints without applying
# their conditions, causing false 400s (e.g. a dated item with order=0 is rejected
# when a global item with the same order exists). The view and DB constraints
# already enforce the correct conditional uniqueness.
validators = []
def validate(self, attrs):
data = super().validate(attrs)