#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 , 17 years ago
| Attachment: | 9029-get_or_create-r9014.diff added |
|---|
comment:2 by , 17 years ago
Replying to mrmachine:
e.g.
Model.objects.filter(relatedfield_id=Ndoes 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 , 17 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 , 16 years ago
| Attachment: | 9029-get-or-create-r12805.diff added |
|---|
Patch with slightly altered test, but no documentation
comment:4 by , 16 years ago
| Has patch: | set |
|---|---|
| Needs documentation: | set |
comment:6 by , 16 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
by , 15 years ago
| Attachment: | 9029-get-or-create-r14733.diff added |
|---|
Updated tests to apply cleanly against r14733.
comment:7 by , 15 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 , 15 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
failing test case