#9029 closed (fixed)
`get_or_create` broken due to inconsistent behaviour between `create` and `filter` on Manager, RelatedManager, QuerySet, etc.
Reported by: | Tai Lee | Owned by: | aaron |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Keywords: | get_or_create get create filter FieldError | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When calling create
, the value for a ForeignKey
field must be an instance of the appropriate model, e.g. Model.objects.create(relatedfield=obj)
. To use a primary key as the value instead of a model instance, you must use the database field name as the keyword, e.g. Model.objects.create(relatedfield_id=N)
.
When calling filter
(or get
), you cannot use the database field name as the keyword, but you can use either a model instance or a primary key as the value, e.g. Model.objects.filter(relatedfield_id=N
does not work, but Model.objects.filter(relatedfield=obj)
and Model.objects.filter(relatedfield=N)
both work.
This makes it impossible to use primary keys as values for ForeignKey
fields with get_or_create
, e.g. Model.objects.get_or_create(relatedfield_id=N, defaults={'otherfield': otherfield})
raises a FieldError
exception.
Attachments (3)
Change History (13)
by , 16 years ago
Attachment: | 9029-get_or_create-r9014.diff added |
---|
comment:2 by , 16 years ago
Replying to mrmachine:
e.g.
Model.objects.filter(relatedfield_id=N
does not work, butModel.objects.filter(relatedfield=obj)
andModel.objects.filter(relatedfield=N)
both work.
How about Model.objects.filter(relatedfield__id=N)
? That usually works. But yes, it does not work with get_or_create and creating new objects, because everything with __
gets stripped for the create query.
comment:3 by , 16 years ago
Triage Stage: | Unreviewed → Accepted |
---|
Julian's right that Model.objects.get_or_create(related__id=N, defaults={'related': related_instance})
works and is an acceptable-if-ugly workaround.
However, there's no reason not to make the test given in the patch work, so I'm marking this accepted. If someone wants to work on it, the place to look is in the QuerySet
implementation.
by , 15 years ago
Attachment: | 9029-get-or-create-r12805.diff added |
---|
Patch with slightly altered test, but no documentation
comment:4 by , 15 years ago
Has patch: | set |
---|---|
Needs documentation: | set |
comment:6 by , 15 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
by , 14 years ago
Attachment: | 9029-get-or-create-r14733.diff added |
---|
Updated tests to apply cleanly against r14733.
comment:7 by , 14 years ago
milestone: | → 1.3 |
---|---|
Triage Stage: | Accepted → Ready for checkin |
Patch looks good to me. Tests updated to apply against r14733, and pass locally on sqlite, postgresql and mysql.
comment:8 by , 14 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
failing test case