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
+
    text = models.CharField(unique_for_date='date')
Suggested changes
-
    text = models.CharField(unique_for_date='date')
+
    text = models.CharField()
+
+
    def save(self, *args, **kwargs):
+
        # more verbose, but less brittle than unique_for_date
+
        if self.objects.filter(date=self.date, text=self.text).exists():
+
            raise ValidationError({'text': 'Must be unique for date.'})
+
        return super().save(*args, **kwargs)
Commit suggestion

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

Read more
Update models.py
We're your Django code review copilot. Get code improvements right in your pull request with our GitHub code review bot.

Configuring this check

Code Review 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 Code Review Doctor.