Opened 9 years ago
Closed 9 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
ORingQobjects, 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 , 9 years ago
comment:2 by , 9 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 , 9 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 , 9 years ago
Mailing list thread: https://groups.google.com/forum/#!topic/django-developers/e3sJ6OiHEd0
comment:5 by , 9 years ago
There currently isn't any way to use
Qobjects when checking for existence inget_or_createandupdate_or_create.
Isn't filter(Q(first_name='Bryan') | Q(first_name='Bruce')).get_or_create({'last_name': 'Harrison'}) working?
comment:6 by , 9 years ago
Replying to charettes:
There currently isn't any way to use
Qobjects when checking for existence inget_or_createandupdate_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 , 9 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