summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authortschilling <schillingt@better-simple.com>2023-01-30 20:39:15 -0600
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-02-14 11:50:35 +0100
commitc5808470aaffda661cb911b06d5b848dd7b75467 (patch)
treefd4e8b25bf9a7fee05cd61f27c6536a57f134a16 /django/db
parentecafcaf634fcef93f9da8cb12795273dd1c3a576 (diff)
downloaddjango-c5808470aaffda661cb911b06d5b848dd7b75467.tar.gz
Fixed #34280 -- Allowed specifying different field values for create operation in QuerySet.update_or_create().
Diffstat (limited to 'django/db')
-rw-r--r--django/db/models/query.py22
1 files changed, 15 insertions, 7 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 9d621c4f69..71bb088679 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -926,25 +926,32 @@ class QuerySet(AltersData):
**kwargs,
)
- def update_or_create(self, defaults=None, **kwargs):
+ def update_or_create(self, defaults=None, create_defaults=None, **kwargs):
"""
Look up an object with the given kwargs, updating one with defaults
- if it exists, otherwise create a new one.
+ if it exists, otherwise create a new one. Optionally, an object can
+ be created with different values than defaults by using
+ create_defaults.
Return a tuple (object, created), where created is a boolean
specifying whether an object was created.
"""
- defaults = defaults or {}
+ if create_defaults is None:
+ update_defaults = create_defaults = defaults or {}
+ else:
+ update_defaults = defaults or {}
self._for_write = True
with transaction.atomic(using=self.db):
# Lock the row so that a concurrent update is blocked until
# update_or_create() has performed its save.
- obj, created = self.select_for_update().get_or_create(defaults, **kwargs)
+ obj, created = self.select_for_update().get_or_create(
+ create_defaults, **kwargs
+ )
if created:
return obj, created
- for k, v in resolve_callables(defaults):
+ for k, v in resolve_callables(update_defaults):
setattr(obj, k, v)
- update_fields = set(defaults)
+ update_fields = set(update_defaults)
concrete_field_names = self.model._meta._non_pk_concrete_field_names
# update_fields does not support non-concrete fields.
if concrete_field_names.issuperset(update_fields):
@@ -964,9 +971,10 @@ class QuerySet(AltersData):
obj.save(using=self.db)
return obj, False
- async def aupdate_or_create(self, defaults=None, **kwargs):
+ async def aupdate_or_create(self, defaults=None, create_defaults=None, **kwargs):
return await sync_to_async(self.update_or_create)(
defaults=defaults,
+ create_defaults=create_defaults,
**kwargs,
)