Opened 7 years ago
Closed 7 years ago
#29051 closed Bug (worksforme)
unique_together behavior undocumented changes in 1.11
Reported by: | Christian Pedersen | Owned by: | nobody |
---|---|---|---|
Component: | Documentation | Version: | 1.11 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
In Django 1.10 unique_together would take complain even if a field was null.
In 1.11 this changed so that it uses the database style, in this case Postgres.
The only thing in the release notes is:
On Oracle, Model.validate_unique() no longer checks empty strings for uniqueness as the database interprets the value as NULL.
no mention of Postgres.
Change History (4)
follow-up: 2 comment:1 by , 7 years ago
comment:2 by , 7 years ago
Replying to Tim Graham:
I'm not sure what you mean -- can you give specific steps to reproduce the problem? The release note you mentioned is from 267dc4adddd2882182f71a7f285a06b1d4b15af0. Is it that same commit that's causing your problem?
Of course. Give this simplified model:
class MyModel(models.Model): field1 = models.ForeignKey(FModel, on_delete=models.CASCADE) field2 = models.CharField() field3 = models.CharField(blank=True, null=True) class Meta: unique_together = (("field1", "field2", "field3"),)
It is possible to do:
MyModel.objects.create(field1=ref, field2='Name', field3=None) MyModel.objects.create(field1=ref, field2='Name', field3=None)
and it will insert this model twice. In Django 1.10 this wouldn't happen, as Django would check all three fields. However in 1.11 it seems to emulate how PostgreSQL does it.
My problem with this is that it's an undocumented change and the only other mention of it I could find was marked as "wontfix".
I believe the commit you mention is the one that changes this behavior. Probably these lines: https://github.com/django/django/commit/267dc4adddd2882182f71a7f285a06b1d4b15af0#diff-bf776a3b8e5dbfac2432015825ef8afeR1090
comment:3 by , 7 years ago
I don't think the code you gave reproduces the issue. It works on all versions of Django that I tested. I imagine the correct steps to reproduce involve a model form.
The release note for 1.11 says, "In model forms, CharField
with null=True
now saves NULL
for blank values instead of empty strings."
The documentation for Field.null says, "In most cases, it’s redundant to have two possible values for “no data;” the Django convention is to use the empty string, not NULL. One exception is when a CharField
has both unique=True
and blank=True
set. In this situation, null=True
is required to avoid unique constraint violations when saving multiple objects with blank values."
The new behavior you mentioned seems to follow naturally if you understand what's happening (for the purposes of a unique constraint, PostgreSQL and other databases don't consider null values equal to each other). I'm not sure that a clarification of the release notes is required but do you want to propose one?
comment:4 by , 7 years ago
Component: | Uncategorized → Documentation |
---|---|
Resolution: | → worksforme |
Status: | new → closed |
I'm not sure what you mean -- can you give specific steps to reproduce the problem? The release note you mentioned is from 267dc4adddd2882182f71a7f285a06b1d4b15af0. Is it that same commit that's causing your problem?