Skip to content
Advertisement

Prevent DateRangeField overlap in Django model?

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

class Booking(models.model):
    # The resource to be reserved
    resource = models.ForeignKey('Resource')
    # When to reserve the resource
    date_range = models.DateRangeField()

    class Meta:
        unique_together = ('resource', 'date_range',)

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

from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import DateTimeRangeField, RangeOperators
from django.db import models
from django.db.models import Q

class Room(models.Model):
    number = models.IntegerField()


class Reservation(models.Model):
    room = models.ForeignKey('Room', on_delete=models.CASCADE)
    timespan = DateTimeRangeField()
    cancelled = models.BooleanField(default=False)

    class Meta:
        constraints = [
            ExclusionConstraint(
                name='exclude_overlapping_reservations',
                expressions=[
                    ('timespan', RangeOperators.OVERLAPS),
                    ('room', RangeOperators.EQUAL),
                ],
                condition=Q(cancelled=False),
            ),
        ]

Postgress Coonstraints

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement