Brittle unique_for

unique_for_date/month/year is very brittle and over time will likely be a source for unexpected behaviour.

unique_for_date/month/year prevents entry of two records with the same value on the same date or month or year.

However, this feature is unfortunately brittle:

  • This constraint is not enforced by the database.
  • It is checked during Model.validate_unique() and so will not occur if is called without first calling Model.validate_unique().
  • The constraint will not be checked even if Model.validate_unique() is called when using a ModelForm that does not include a field involved in the check.
  • Only the date portion of the field will be considered, even when validating a DateTimeField.

Most of these problems can be mitigated by moving the validation to

So in practice, do this

class SomeModel(models.Model):
    date = models.DateField()
    text = models.CharField()

    def save(self, *args, **kwargs):
        if self.objects.filter(, text=self.text).exists():
            raise ValidationError({'text': 'Must be unique for date.'})
        return super().save(*args, **kwargs)

Instead of this

class SomeModel(models.Model):
    date = models.DateField()
    text = models.CharField(unique_for='date')

Are you affected by this? Audit your codebase in seconds to find out.

Configuring this check

Django Doctor will run this check by default. No configuration is needed but the check can be turned on/off using check code brittle-unique-for in your pyproject.toml file.

Read more about configuring Django Doctor.