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 Model.save() 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 Model.save().

If our GitHub code review bot spots this issue in your pull request it gives this advice:

django-doctorbotsuggested changes just now
models.py
1
+
class ExampleModel(models.Model):
2
+
    date = models.DateField()
3
+
    foo = models.CharField(unique_for_date='date')

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

Read more
Suggested changes
-
    foo = models.CharField(unique_for_date='date')
+
    foo = models.CharField()
+
+
    def save(self, *args, **kwargs):
+
        # more verbose, but less brittle than unique_for_date
+
        if self.objects.filter(date=self.date, foo=self.foo).exists():
+
            raise ValidationError({'foo': 'Must be unique for date.'})
+
        return super().save(*args, **kwargs)
Commit suggestion
Update models.py

Instantly check if you have this issue for free

    Works with tools you use

    Read about how it works.