Django constraint on derived fields

I am trying to add a non-overlaping constraint on a Postgres specific field DateRange field:

from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import DateRangeField, RangeOperators

class MyModel(models.Model):
    timespan = DateRangeField(blank=False, null=False)
    status = models.CharField(max_length=8, choices=status_choices, blank=False, null=False)

    class Meta:
        constraints = [
            ExclusionConstraint(
                name='exclude_overlapping_offer', 
                expressions=[
                    ('timespan', RangeOperators.OVERLAPS),
                    (models.Q(status='ACCEPTED'), RangeOperators.EQUAL),
                ],
            )

Basically I want to prevent having overlapping entries in the database that have status ACCEPTED.

The migration runs fine, but then when I try to save the model, I get an error:

AttributeError: 'Q' object has no attribute 'replace_expressions'

There is a reply on a bug report that says that Q objects are not allowed in the expressions of the constraint:

https://code.djangoproject.com/ticket/34805

Is there some other way to have the constraint on a derived field?

The answer lies here:

https://docs.djangoproject.com/en/5.1/ref/contrib/postgres/constraints/

condition

ExclusionConstraint.condition A Q object that specifies the condition to restrict a constraint to a subset of rows. For example, condition=Q(cancelled=False). These conditions have the same database restrictions as django.db.models.Index.condition

Use condition to supply the non-range value you want to filter the rows you want to apply the range restrictions to.

Вернуться на верх