Opened 8 years ago
Closed 8 years ago
#27249 closed Cleanup/optimization (duplicate)
IntegrityError when using ManyToManyField.add() with a value of incorrect type
Reported by: | Sjoerd Job Postmus | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | manytomanyfield, integrityerror |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When specifying the primary keys of objects to related_manager.add
, one has to use the same type as the database returns, at the risk of getting an IntegrityError
.
Example (using Django contrib.auth).
>>> from django.contrib.auth.models import Group, Permission >>> group = Group.objects.create() >>> permission = Permission.objects.first() >>> print(permission.pk) 1 >>> group.permissions.add(permission.pk) >>> group.permissions.add(permission.pk) >>> group.permissions.add(str(permission.pk)) Traceback (most recent call last): ... <snip> ... IntegrityError: UNIQUE constraint failed: auth_group_permissions.group_id, auth_group_permissions.permission_id >>> group.permissions.add(permission.pk) >>> group.permissions.add(permission.pk)
Now of course, I assume nobody would do an explicit call to str()
there, but if the primary keys come from another input source (like: a URL), it is not unlikely to expect them to not be the same type as the database uses.
(seen in 1.9.6, 1.10.1 and master).
Not sure about how to fix it, because the type of the primary key might not necessarily be an integer.
Change History (2)
comment:1 by , 8 years ago
Summary: | IntegrityError when using ManyToManyField.add due to type confusion → IntegrityError when using ManyToManyField.add() with a value of incorrect type |
---|---|
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → Cleanup/optimization |
I guess as long as the performance penalty isn't too large, a possibility could be to call
Field.to_python()
on the input.