Opened 8 years ago
Closed 8 years ago
#27070 closed New feature (invalid)
Support for `Q` objects in `get_or_create` and `update_or_create`
Reported by: | Flavio Curella | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Someday/Maybe | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Since Q
objects can be used to .filter
queryset,I think it would make sense to leverage their functionality when looking up for objects in get_or_create
or update_or_create
.
There currently isn't any way to use Q
objects when checking for existence in get_or_create
and update_or_create
. There are two main reasons for that:
- The signature of these methods prevents the usage of unnamed arguments
- When
OR
ingQ
objects, if the lookup fails, and those fields are not specified indefaults
, we have undefined values for the object that we need to create.
We could address 1. by adding a keyword argument (let's call it query
for now), so that the signature would be get_or_create(defaults=None, query=None, **kwargs)
. It could then be used in this way:
obj, created = Person.objects.get_or_create( query=Q(first_name="George") | Q(first_name='Bruce'), defaults={"last_name": "Harrison"}, )
Re 2., we have two options:
2a. Leave the ambiguous fields undefined (but this would be inconsistent with the 'non-query
' behavior).
2b. Force the user to specify the field in defaults
by raising some exception. Not happy about duplicating data in query
and in defaults
Change History (7)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
Triage Stage: | Unreviewed → Someday/Maybe |
---|
I'm not immediately convinced the additional complexity is a good idea. Don't forget that adding a new keyword argument to get_or_create()
could be backwards-incompatible for any models that have that field name. Could you write to the DevelopersMailingList to get some feedback?
comment:3 by , 8 years ago
One thing I like about this proposal is that it makes the functionality of get_or_create()
and update_or_create()
feel more consistent with other query methods that can use Q
objects like get()
, filter()
etc. We would probably want to use a similar argument like defaults__exact
for the case of a model having query
as a field name.
comment:4 by , 8 years ago
Mailing list thread: https://groups.google.com/forum/#!topic/django-developers/e3sJ6OiHEd0
comment:5 by , 8 years ago
There currently isn't any way to use
Q
objects when checking for existence inget_or_create
andupdate_or_create
.
Isn't filter(Q(first_name='Bryan') | Q(first_name='Bruce')).get_or_create({'last_name': 'Harrison'})
working?
comment:6 by , 8 years ago
Replying to charettes:
There currently isn't any way to use
Q
objects when checking for existence inget_or_create
andupdate_or_create
.
Isn't
filter(Q(first_name='Bryan') | Q(first_name='Bruce')).get_or_create({'last_name': 'Harrison'})
working?
O_O It didn't occur to me that it could be done that way. Seems to work exactly as I'd expect.
Should I update my PR to simply add some tests of combining .filter
with .get_or_create
and maybe show an example in the docs?
comment:7 by , 8 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
On a second thought, I dont think more work on the docs is necessary. Closing as 'invalid'
Proof of concept at https://github.com/django/django/pull/7101