[Django] #36872: Django's template engine cannot handle asynchronous methods

3 views
Skip to first unread message

Django

unread,
Jan 20, 2026, 4:56:48 AM (3 days ago) Jan 20
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: rrobles | Type: Bug
Status: new | Component: Template
| system
Version: 6.0 | Severity: Normal
Keywords: Template, Async | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 1
-------------------------------------+-------------------------------------
Currently, the Django template is not designed to execute asynchronous
methods; it is only designed to execute synchronous methods.

Here's an example of how to reproduce the error:


{{{
from django.template import engines

django_engine = engines['django']

class Example:
def sync_method(self):
return "Synchronous Method Result"
async def async_method(self):
return "Asynchronous Method Result"

html_string = """
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>sync: {{ example.sync_method }}!</h1>
<p>async: {{ example.async_method }}</p>
</body>
</html>
"""

template = django_engine.from_string(html_string)
rendered_html = template.render({'example': Example()})

print(rendered_html)
}}}

This will return this error:

{{{
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>sync: Synchronous Method Result!</h1>
<p>async: &lt;coroutine object Example.async_method at
0x7bdeeb9aa980&gt;</p>
</body>
</html>
}}}

I had thought that a solution to this error might be to modify the resolve
method of the FilterExpression class
https://github.com/django/django/blob/main/django/template/base.py#L785

If we add this:

{{{
class FilterExpression:
...

def resolve(self, context, ignore_failures=False):
if self.is_var:
try:
obj = self.var.resolve(context)

# My proposal begins
if asyncio.iscoroutine(obj):
try:
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

if loop.is_running():
obj = loop.run_until_complete(obj)
else:
obj = asyncio.run(obj)
# My proposal ends

except VariableDoesNotExist:
...
}}}

Now it renders correctly:

{{{
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>sync: Synchronous Method Result!</h1>
<p>async: Asynchronous Method Result</p>
</body>
</html>
}}}

I use Django ASGI a lot at work, and there are many features like this
that would be very useful. I look forward to your feedback.
--
Ticket URL: <https://code.djangoproject.com/ticket/36872>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jan 21, 2026, 6:44:04 AM (yesterday) Jan 21
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
---------------------------------+--------------------------------------
Reporter: Ricardo Robles | Owner: (none)
Type: Bug | Status: new
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 1
---------------------------------+--------------------------------------
Comment (by Zachary W):

Could be related. There is an **async_to_sync** function in **asgiref**:
https://github.com/django/asgiref/blob/2b28409ab83b3e4cf6fed9019403b71f8d7d1c51/asgiref/sync.py#L585
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:1>

Django

unread,
Jan 21, 2026, 7:48:34 AM (yesterday) Jan 21
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
---------------------------------+--------------------------------------
Reporter: Ricardo Robles | Owner: (none)
Type: Bug | Status: new
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 1
---------------------------------+--------------------------------------
Comment (by Ricardo Robles):

Replying to [comment:1 Zachary W]:
> Could be related. There is an **async_to_sync** function in **asgiref**:
https://github.com/django/asgiref/blob/2b28409ab83b3e4cf6fed9019403b71f8d7d1c51/asgiref/sync.py#L585

You're correct, the most elegant and simple way to do it would be:
{{{
def resolve(self, context, ignore_failures=False):
if self.is_var:
try:
obj = self.var.resolve(context)
if asyncio.iscoroutine(obj):
obj = async_to_sync(lambda: obj)()
...

}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:2>

Django

unread,
Jan 21, 2026, 7:49:55 AM (yesterday) Jan 21
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
---------------------------------+--------------------------------------
Reporter: Ricardo Robles | Owner: (none)
Type: Bug | Status: new
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 1
---------------------------------+--------------------------------------
Description changed by Ricardo Robles:

Old description:
> def resolve(self, context, ignore_failures=False):
> if self.is_var:
> try:
> obj = self.var.resolve(context)
>
New description:
def resolve(self, context, ignore_failures=False):
if self.is_var:
try:
obj = self.var.resolve(context)

# My proposal begins
if asyncio.iscoroutine(obj):
obj = async_to_sync(lambda: obj)()
# My proposal ends

except VariableDoesNotExist:
...
}}}

Now it renders correctly:

{{{
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>sync: Synchronous Method Result!</h1>
<p>async: Asynchronous Method Result</p>
</body>
</html>
}}}

I use Django ASGI a lot at work, and there are many features like this
that would be very useful. I look forward to your feedback.

--
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:3>

Django

unread,
3:06 AM (18 hours ago) 3:06 AM
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner:
| itzmehaksharma89-cell
Type: Bug | Status: assigned
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 1
-------------------------------------+-------------------------------------
Changes (by itzmehaksharma89-cell):

* owner: (none) => itzmehaksharma89-cell
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:4>

Django

unread,
3:36 AM (18 hours ago) 3:36 AM
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner:
| itzmehaksharma89-cell
Type: Bug | Status: assigned
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 1
-------------------------------------+-------------------------------------
Changes (by Ricardo Robles):

* Attachment "proposal.diff" added.

Django

unread,
6:07 AM (15 hours ago) 6:07 AM
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner: Ricardo
| Robles
Type: Bug | Status: assigned
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 1
-------------------------------------+-------------------------------------
Changes (by Ricardo Robles):

* owner: itzmehaksharma89-cell => Ricardo Robles

--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:5>

Django

unread,
8:21 PM (1 hour ago) 8:21 PM
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner: Ricardo
| Robles
Type: Bug | Status: assigned
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* stage: Unreviewed => Accepted
* ui_ux: 1 => 0

Comment:

Thanks, I think it makes sense to have this. The provided patch is non-
invasive, and I don't think anyone wants the current behavior with the
memory address of the coroutine rendered into the template (and
`RuntimeWarning` at shutdown for a coroutine not awaited).

[https://github.com/django/django/pull/20570 PR]
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:6>

Django

unread,
8:22 PM (1 hour ago) 8:22 PM
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner: Ricardo
| Robles
Type: Bug | Status: assigned
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* has_patch: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:7>
Reply all
Reply to author
Forward
0 new messages