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:
Model.validate_unique()
and so will not occur if Model.save() is called without first calling Model.validate_unique()
.Model.validate_unique()
is called when using a ModelForm that does not include a field involved in the check.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:
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.
- | 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) |