#36235: RelatedManager.all().get_or_create() does not work
-------------------------------------+-------------------------------------
     Reporter:  Nick Pope            |                    Owner:  (none)
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  dev
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:  get_or_create,       |             Triage Stage:
  related, manager                   |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by Nick Pope:

Old description:

> When accessing the queryset for a related manager, `.get_or_create()` and
> `.update_or_create()` lose context of the related instance.
>
> Calling on the related manager works as expected:
>
> {{{#!python
> publisher.books.get_or_create(name="The Very Hungry Caterpillar")
> }}}
>
> This is the case that was fixed by #3121 and #23611.
>
> But calling on the queryset causes an `IntegrityError` to be raised:
>
> {{{#!python
> publisher.books.all().get_or_create(name="The Very Hungry Caterpillar")
> }}}
>
> This can be a subtle failure that is hard to understand, especially if
> `publisher.books.all()` is assigned to a variable earlier.
>
> The challenge here is that the overridden methods on the manager set
> `kwargs[self.field.name] = self.instance`.
>
> We'd need to be able to pass this information down to the queryset. It
> looks like this might already be available in `_known_related_objects`
> which is set by `RelatedManager._apply_rel_filters()`, so that would be a
> good starting point for investigation.
>
> If this is something we can't fix reliably, then we should update the
> admonition under
> [https://docs.djangoproject.com/en/stable/ref/models/querysets/#get-or-
> create .get_or_create()] in the docs and probably update
> [https://docs.djangoproject.com/en/stable/ref/models/querysets/#update-
> or-create .update_or_create()] to make this and other issues related to
> use through `RelatedManager` more clear.

New description:

 When accessing the queryset for a related manager, `.get_or_create()` and
 `.update_or_create()` lose context of the related instance.

 Calling on the related manager works as expected:

 {{{#!python
 publisher.books.get_or_create(name="The Very Hungry Caterpillar")
 }}}

 This is the case that was fixed by #3121 and #23611.

 But calling on the queryset causes an `IntegrityError` to be raised:

 {{{#!python
 publisher.books.all().get_or_create(name="The Very Hungry Caterpillar")
 }}}

 This can be a subtle failure that is hard to understand, especially if
 `publisher.books.all()` is assigned to a variable earlier.

 The challenge here is that the overridden methods on the manager set
 `kwargs[self.field.name] = self.instance`.

 We'd need to be able to pass this information down to the queryset. It
 looks like this might already be available in `_known_related_objects`
 which is set by `RelatedManager._apply_rel_filters()`, so that would be a
 good starting point for investigation.

 We would also need to check whether something needs to be done to select
 the correct database as `RelatedManager.get_or_create()` has handling for
 this:

 {{{#!python
             db = router.db_for_write(self.model, instance=self.instance)
 }}}

 If this is something we can't fix reliably, then we should update the
 admonition under
 [https://docs.djangoproject.com/en/stable/ref/models/querysets/#get-or-
 create .get_or_create()] in the docs and probably update
 [https://docs.djangoproject.com/en/stable/ref/models/querysets/#update-or-
 create .update_or_create()] to make this and other issues related to use
 through `RelatedManager` more clear.

--
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36235#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/01070195705d2f3d-cf4fb62b-c4fe-46b3-96e3-13f1b5073882-000000%40eu-central-1.amazonses.com.

Reply via email to