The hidden pitfalls of unique_for_date

Can you spot the maintainability problem with this code?

from django.db import modelsclass MyModel(models.Model):
date = models.DateField()
text = models.CharField(unique_for_date='date')

unique_for_date is the culprit. It’s meant to make sure text will be unique for date. However, unique_for_date has a pitfalls:

That’s a lot of caveats to keep in mind when building a mental model of the code we’re working on. Lots of room there for the unexpected to creep in:

So unique_for has many pitfalls to be triggered by human error. When implementing the fields the developer may conclude that these problems don’t apply for the specific problem they’re solving, and they trust themselves, their current and future team mates not to make mistakes. However, over time requirements changes. Over time things tend to get more different, not more similar. Code entropy is real. As the situation on the ground changes can we be sure that one of those problems won’t be hit? What’s your risk appetite?

Avoiding the problem

Instead of nice and small but brittle:

from django.db import modelsclass MyModel(models.Model):
date = models.DateField()
text = models.CharField(unique_for_date=’date’)

We can do a more verbose, less DRY, but simultaneously more explicit and more future proof:

class ExampleModel(models.Model):
date = models.DateField()
text= models.CharField()
def save(self, *args, **kwargs):
# change specific filter depending on need.
if self.objects.filter(date=self.date, text=self.text).exists():
raise ValidationError({‘name’: ‘Nein!’})
return super().save(*args, **kwargs)

This validation will be called whenever Model.save() is called, but unfortunately not when Model.objects.update() is called, but there’s no silver bullet here.

Does your codebase use `unique_for`?

It’s easy for tech debt to slip in. I can check that for you at django.doctor. I’m a GitHub bot that suggest Django improvements to your code:

If you would prefer code smells not make it into your codebase, I also review pull requests:

See the GitHub PR bot and reduce dev effort of improving your code.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store