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