diff options
| author | Alexander <homm86@gmail.com> | 2020-08-26 13:26:19 +0300 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-08-27 11:46:47 +0200 |
| commit | 20d38fd75903b58335abd8e7cc576a1f1219a4fa (patch) | |
| tree | 2e4dce419ece528a9da65db0a56e065d2a773b07 | |
| parent | 1251772cb83aa4106f526fe00738e51c0eb59122 (diff) | |
Fixed #31947 -- Made QuerySet.update_or_create() reuse get_or_create().
| -rw-r--r-- | django/db/models/query.py | 46 |
1 files changed, 17 insertions, 29 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py index b39a988ab0..b48d0df9c0 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -573,7 +573,17 @@ class QuerySet: return self.get(**kwargs), False except self.model.DoesNotExist: params = self._extract_model_params(defaults, **kwargs) - return self._create_object_from_params(kwargs, params) + # Try to create an object using passed params. + try: + with transaction.atomic(using=self.db): + params = dict(resolve_callables(params)) + return self.create(**params), True + except IntegrityError: + try: + return self.get(**kwargs), False + except self.model.DoesNotExist: + pass + raise def update_or_create(self, defaults=None, **kwargs): """ @@ -585,42 +595,20 @@ class QuerySet: defaults = defaults or {} self._for_write = True with transaction.atomic(using=self.db): - try: - obj = self.select_for_update().get(**kwargs) - except self.model.DoesNotExist: - params = self._extract_model_params(defaults, **kwargs) - # Lock the row so that a concurrent update is blocked until - # after update_or_create() has performed its save. - obj, created = self._create_object_from_params(kwargs, params, lock=True) - if created: - return obj, created + # 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) + if created: + return obj, created for k, v in resolve_callables(defaults): setattr(obj, k, v) obj.save(using=self.db) return obj, False - def _create_object_from_params(self, lookup, params, lock=False): - """ - Try to create an object using passed params. Used by get_or_create() - and update_or_create(). - """ - try: - with transaction.atomic(using=self.db): - params = dict(resolve_callables(params)) - obj = self.create(**params) - return obj, True - except IntegrityError: - try: - qs = self.select_for_update() if lock else self - return qs.get(**lookup), False - except self.model.DoesNotExist: - pass - raise - def _extract_model_params(self, defaults, **kwargs): """ Prepare `params` for creating a model instance based on the given - kwargs; for use by get_or_create() and update_or_create(). + kwargs; for use by get_or_create(). """ defaults = defaults or {} params = {k: v for k, v in kwargs.items() if LOOKUP_SEP not in k} |
