3

I want to bulk update a table with data two tables over. A solution has been given for the simpler case mentioned in the documentation of:

Entry.objects.update(headline=F('blog__name'))

For that solution, see

https://stackoverflow.com/a/50561753/1092940

Expanding from the example, imagine that Entry has a Foreign Key reference to Blog via a field named blog, and that Blog has a Foreign Key reference to User via a field named author. I want the equivalent of:

Entry.objects.update(author_name=F('blog__author__username'))

As in the prior solution, the solution is expected to employ SubQuery and OuterRef.

The reason I ask here is because I lack confidence where this problem starts to employ multiple OuterRefs, and confusion arises about which outer ref it refers to.

AlanSE
  • 2,597
  • 2
  • 29
  • 22

1 Answers1

1

The reason I ask here is because I lack confidence where this problem starts to employ multiple OuterRefs, and confusion arises about which outer ref it refers to.

It does not require multiple outer references, you can update with:

from django.db.models import OuterRef, Subquery

author_name = Author.objects.filter(
    blogs__id=OuterRef('blog_id')
).values_list(
    'username'
)[:1]

Entry.objects.update(
    author_name=Subquery(author_name)
)

You here thus specify that you look for an Author with a related Blog with an id equal to the blog_id of the Entry.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • The related name from `Author` back to `Blog` would more likely be `blogs` because an author can have multiple blogs. That said, I think I still might get this. Still chewing on it. – AlanSE Aug 08 '19 at 13:05
  • @AlanSE: If no `related_name` is specified, it is `blog__`, otherwise it is `related_name__id` (of course with `related_name` the related name). – Willem Van Onsem Aug 08 '19 at 13:07
  • 1
    All along I had assumed that nested `Subquery`s would be necessary. After much deeper investigation of my own problem (no longer a series of forward ForeignKeys), as well as your example, it turned out to not be necessary in any case. Thanks, this is resolved. – AlanSE Aug 09 '19 at 13:05