Range fields store an interval (e.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | # ====================================================================== # Range fields store an interval (e.g. a booking's start/end) in a single # column. `__contains` tests membership. The `ExclusionConstraint` uses the `&&` # overlap operator to forbid two reservations for the same room from overlapping # — enforced by the database. # ====================================================================== # ---------------------------------------------------------------------- # reservations covering 2026-06-03 # ---------------------------------------------------------------------- # Django: probe = datetime(2026, 6, 3, tzinfo=timezone.utc) Reservation.objects.filter(during__contains=probe) # SQL: # SELECT "examples_reservation"."id", "examples_reservation"."room", "examples_reservation"."during", "examples_reservation"."price_band", "examples_reservation"."date_span", "examples_reservation"."amount", "examples_reservation"."seq" # FROM "examples_reservation" # WHERE "examples_reservation"."during" @> '2026-06-03 00:00:00+00:00'::timestamptz::timestamp with time zone # Result: # room 101 [2026-06-01 00:00:00+00:00, 2026-06-05 00:00:00+00:00) # room 202 [2026-06-02 00:00:00+00:00, 2026-06-06 00:00:00+00:00) # ---------------------------------------------------------------------- # insert OVERLAPPING reservation for room 101 # ---------------------------------------------------------------------- # Django: # blocked by the EXCLUDE constraint (room = ... && during overlaps) Reservation.objects.create( room=101, during=Range(datetime(2026, 6, 3, tzinfo=timezone.utc), datetime(2026, 6, 7, tzinfo=timezone.utc)), ) # SQL: # BEGIN # # INSERT INTO "examples_reservation" ("room", "during", "price_band", "date_span", "amount", "seq") # VALUES (101, '["2026-06-03 00:00:00+00:00","2026-06-07 00:00:00+00:00")'::tstzrange::tstzrange, NULL::int4range, NULL::daterange, NULL::numrange, NULL::int8range) # RETURNING "examples_reservation"."id" # # ROLLBACK # Result: # correctly rejected: conflicting key value violates exclusion constraint "exclude_overlapping_reservations" |