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 (
- Which method (
save()?) would I need to override to catch the
IntegrityErrorraised by the constraint?
[Django 4.1.5/Python 3.11.1/PostgreSQL 14.6]