Now that Django supports the DateRangeField, is there a ‘Pythonic’ way to prevent records from having overlapping date ranges?
Hypothetical use case
One hypothetical use case would be a booking system, where you don’t want people to book the same resource at the same time.
Hypothetical example code
JavaScript
x
9
1
class Booking(models.model):
2
# The resource to be reserved
3
resource = models.ForeignKey('Resource')
4
# When to reserve the resource
5
date_range = models.DateRangeField()
6
7
class Meta:
8
unique_together = ('resource', 'date_range',)
9
Advertisement
Answer
I know that the answer is old, but now you can just create a constraint in the meta of the model, that will make Postgres handle this
JavaScript
1
26
26
1
from django.contrib.postgres.constraints import ExclusionConstraint
2
from django.contrib.postgres.fields import DateTimeRangeField, RangeOperators
3
from django.db import models
4
from django.db.models import Q
5
6
class Room(models.Model):
7
number = models.IntegerField()
8
9
10
class Reservation(models.Model):
11
room = models.ForeignKey('Room', on_delete=models.CASCADE)
12
timespan = DateTimeRangeField()
13
cancelled = models.BooleanField(default=False)
14
15
class Meta:
16
constraints = [
17
ExclusionConstraint(
18
name='exclude_overlapping_reservations',
19
expressions=[
20
('timespan', RangeOperators.OVERLAPS),
21
('room', RangeOperators.EQUAL),
22
],
23
condition=Q(cancelled=False),
24
),
25
]
26