Cannot access ForeignKey in acync context

I have a swapped User model and I added some other fields such as post_1 referred to Post Model.

account/models.py

class CustomUser(AbstractUser):
    ...
    post_1 = models.ForeignKey(Post, on_delete=models.SET_NULL, null=True, blank=True, related_name='post_1')
    ...

account/view.py

async def index(request):
    user = await request.auser()
    if not user.is_authenticated:
        return HttpResponseRedirect(reverse('account:login') + f'?next={request.path}')

    return render(request, 'account/detail.html', context={
        'user_post_1': user.post_1,  # <- Raises SynchronousOnlyOperation
        'user_post_2': user.post_2,
    })

Didn’t find any clue in ForeignKey ref doc.

This is correct.

This line:

retrieves a reference to the User object, not any related objects.

The reference user.post_1 requires a query to retrieve the instance of Post, and so needs to be executed synchronously, or otherwise retrieved using one of the asynchronous functions.

So what asynchronous functions should I use to retrieve the instance of Post, like sync_to_async()? Must related objects be retrived in sync?
Didn’t find any native async methods to do this in ForeignKey ref doc.

You could create the context dict in a function wrapped by sync_to_async.

If you didn’t want to retrieve it in sync mode, I believe you could rewrite it as a query using the async methods.

So, instead of:

I think this would work:
'user_post_1': await Post.objects.aget(id=user.post_1_id),
'user_post_2': await Post.objects.aget(id=user.post_2_id),

Or, since you have two of these to retrieve, instead of retrieving post_1 and post_2 individually, you could use the ain_buik method to retrieve them both:

posts = await Post.objects.ain_bulk([user.post_1_id, user.post_2_id])
return render(request, 'account/detail.html', context={
    'user_post_1': posts[user.post_1_id],
    'user_post_2': posts[user.post_2_id],
})
1 Like