Django template tags with async view

As soon as I add async in front of a view, my template which contains {% if request.user.is_authenticated %} causes a SynchronousOnlyOperation, You cannot call this from an async context - use a thread or sync_to_async.

The error only occurs when a user is logged in. What am I not getting here?

view

async def test(request):
    return render(request, 'test.html')

template, test.html

{% if request.user.is_authenticated %}
<script>
  const usr = "{{user}}";
</script>
{% endif %}

When the current user is not authenticated, request.user is an AnonymousUser, so is_authenticated is just false. However, when request.user is an actual user, it needs to check through the ORM if the user is authenticated. The ORM is synchronous (except in a few situations), so this doesn't work in an async context. To make this work, use sync_to_async in the view:

from asgiref.sync import sync_to_async
async def test(request):
    return render(request, 'test.html', {"is_authenticated": await sync_to_async(lambda: request.user.is_authenticated)})

And in test.html:

{% if is_authenticated %}
<script>
  const usr = "{{user}}";
</script>
{% endif %}

I know it's a pain, but for now it's the only way. Here's hoping that Django will add asynchronous support ORM-wide in the next release.

Back to Top