DB constraints vs. clean() method in Django
After creating a clean()
method to avoid overlapping date ranges in an admin form, I added an ExclusionContraint
to ensure integrity at the DB level, too:
class DateRangeFunc(models.Func):
function = 'daterange'
output_field = DateRangeField()
class Occupancy(models.Model):
unit = models.ForeignKey(Unit, on_delete=models.CASCADE)
number_of = models.IntegerField()
begin = models.DateField()
end = models.DateField(default=datetime.date(9999,12,31))
class Meta:
constraints = [
ExclusionConstraint(
name="exclude_overlapping_occupancies",
expressions=(
(
DateRangeFunc(
"begin", "end", RangeBoundary(inclusive_lower=True, inclusive_upper=True)
),
RangeOperators.OVERLAPS,
),
("unit", RangeOperators.EQUAL),
),
),
]
This constraint works as expected, but it seems to precede clean()
, because any overlap raises an IntegrityError
for the admin form. I would have expected that clean()
is called first.
I have two questions (related, but not identical to this question):
- Is there any way to change the order of evaluation (
clean()
→ExclusionConstraint
)? - Which method (
save()
?) would I need to override to catch theIntegrityError
raised by the constraint?
[Django 4.1.5/Python 3.11.1/PostgreSQL 14.6]