diff options
| author | Jon Janzen <jon@jonjanzen.com> | 2022-11-04 15:22:32 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-11-08 08:13:56 +0100 |
| commit | 9fb57fcc703749269987f54f9ee1d71bd9a2dbca (patch) | |
| tree | 494a8b6dc0c44c75c5c5b0862554e76a01e2b304 /django | |
| parent | 8740d2f452186b30374bf29240144a5048ae0eb4 (diff) | |
[4.1.x] Fixed #34139 -- Fixed acreate(), aget_or_create(), and aupdate_or_create() methods for related managers.
Bug in 58b27e0dbb3d31ca1438790870b2b51ecdb10500.
Backport of 7b94847e384b1a8c05a7d4c8778958c0290bdf9a from main
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/contenttypes/fields.py | 17 | ||||
| -rw-r--r-- | django/db/models/fields/related_descriptors.py | 38 |
2 files changed, 55 insertions, 0 deletions
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py index 5bb4cb008f..c4b80b3677 100644 --- a/django/contrib/contenttypes/fields.py +++ b/django/contrib/contenttypes/fields.py @@ -2,6 +2,8 @@ import functools import itertools from collections import defaultdict +from asgiref.sync import sync_to_async + from django.contrib.contenttypes.models import ContentType from django.core import checks from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist @@ -744,6 +746,11 @@ def create_generic_related_manager(superclass, rel): create.alters_data = True + async def acreate(self, **kwargs): + return await sync_to_async(self.create)(**kwargs) + + acreate.alters_data = True + def get_or_create(self, **kwargs): kwargs[self.content_type_field_name] = self.content_type kwargs[self.object_id_field_name] = self.pk_val @@ -752,6 +759,11 @@ def create_generic_related_manager(superclass, rel): get_or_create.alters_data = True + async def aget_or_create(self, **kwargs): + return await sync_to_async(self.get_or_create)(**kwargs) + + aget_or_create.alters_data = True + def update_or_create(self, **kwargs): kwargs[self.content_type_field_name] = self.content_type kwargs[self.object_id_field_name] = self.pk_val @@ -760,4 +772,9 @@ def create_generic_related_manager(superclass, rel): update_or_create.alters_data = True + async def aupdate_or_create(self, **kwargs): + return await sync_to_async(self.update_or_create)(**kwargs) + + aupdate_or_create.alters_data = True + return GenericRelatedObjectManager diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index bacf2148b4..3baa9313fb 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -63,6 +63,8 @@ and two directions (forward and reverse) for a total of six combinations. ``ReverseManyToManyDescriptor``, use ``ManyToManyDescriptor`` instead. """ +from asgiref.sync import sync_to_async + from django.core.exceptions import FieldError from django.db import connections, router, transaction from django.db.models import Q, signals @@ -765,6 +767,11 @@ def create_reverse_many_to_one_manager(superclass, rel): create.alters_data = True + async def acreate(self, **kwargs): + return await sync_to_async(self.create)(**kwargs) + + acreate.alters_data = True + def get_or_create(self, **kwargs): self._check_fk_val() kwargs[self.field.name] = self.instance @@ -773,6 +780,11 @@ def create_reverse_many_to_one_manager(superclass, rel): get_or_create.alters_data = True + async def aget_or_create(self, **kwargs): + return await sync_to_async(self.get_or_create)(**kwargs) + + aget_or_create.alters_data = True + def update_or_create(self, **kwargs): self._check_fk_val() kwargs[self.field.name] = self.instance @@ -781,6 +793,11 @@ def create_reverse_many_to_one_manager(superclass, rel): update_or_create.alters_data = True + async def aupdate_or_create(self, **kwargs): + return await sync_to_async(self.update_or_create)(**kwargs) + + aupdate_or_create.alters_data = True + # remove() and clear() are only provided if the ForeignKey can have a # value of null. if rel.field.null: @@ -1161,6 +1178,13 @@ def create_forward_many_to_many_manager(superclass, rel, reverse): create.alters_data = True + async def acreate(self, *, through_defaults=None, **kwargs): + return await sync_to_async(self.create)( + through_defaults=through_defaults, **kwargs + ) + + acreate.alters_data = True + def get_or_create(self, *, through_defaults=None, **kwargs): db = router.db_for_write(self.instance.__class__, instance=self.instance) obj, created = super(ManyRelatedManager, self.db_manager(db)).get_or_create( @@ -1174,6 +1198,13 @@ def create_forward_many_to_many_manager(superclass, rel, reverse): get_or_create.alters_data = True + async def aget_or_create(self, *, through_defaults=None, **kwargs): + return await sync_to_async(self.get_or_create)( + through_defaults=through_defaults, **kwargs + ) + + aget_or_create.alters_data = True + def update_or_create(self, *, through_defaults=None, **kwargs): db = router.db_for_write(self.instance.__class__, instance=self.instance) obj, created = super( @@ -1187,6 +1218,13 @@ def create_forward_many_to_many_manager(superclass, rel, reverse): update_or_create.alters_data = True + async def aupdate_or_create(self, *, through_defaults=None, **kwargs): + return await sync_to_async(self.update_or_create)( + through_defaults=through_defaults, **kwargs + ) + + aupdate_or_create.alters_data = True + def _get_target_ids(self, target_field_name, objs): """ Return the set of ids of `objs` that the target field references. |
