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

5 views
Skip to first unread message

Django

unread,
Jan 20, 2026, 4:56:48 AM (4 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 (3 days ago) 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 (3 days ago) 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 (3 days ago) 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,
Jan 22, 2026, 3:06:03 AM (2 days ago) Jan 22
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,
Jan 22, 2026, 3:36:39 AM (2 days ago) Jan 22
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,
Jan 22, 2026, 6:07:55 AM (2 days ago) Jan 22
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,
Jan 22, 2026, 8:21:40 PM (2 days ago) Jan 22
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,
Jan 22, 2026, 8:22:10 PM (2 days ago) Jan 22
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>

Django

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

* needs_docs: 0 => 1
* type: Bug => New feature

Comment:

I think this will need a sliver of documentation. For instance where we
say:

> If the resulting value is callable, it is called with no arguments.

We could augment it with:

> If the resulting value is a coroutine, it is awaited via
`async_to_sync()`.

or similar.

Although this is sort of a bug since elsewhere the docs say "variables are
evaluated", I think we should let folks know we added this with a release
note and versionchanged annotation.
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:8>

Django

unread,
Jan 23, 2026, 9:12:13 AM (yesterday) Jan 23
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner: Ricardo
| Robles
Type: New feature | Status: assigned
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Ricardo Robles):

* Attachment "proposal_2.diff" added.

Django

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

Replying to [comment:8 Jacob Walls]:
> I think this will need a sliver of documentation. For instance where we
say:
>
> > If the resulting value is callable, it is called with no arguments.
>
> We could augment it with:
>
> > If the resulting value is a coroutine, it is awaited via
`async_to_sync()`.
>
> or similar.
>
> Although this is sort of a bug since elsewhere the docs say "variables
are evaluated", I think we should let folks know we added this with a
release note and versionchanged annotation.


Good afternoon,

Okay, I've just updated the documentation in both the diff and the PR to
include this information.
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:9>

Django

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

* needs_better_patch: 0 => 1

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

Django

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

* cc: Carlton Gibson (added)

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

Django

unread,
Jan 23, 2026, 3:16:35 PM (20 hours ago) Jan 23
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner: Ricardo
| Robles
Type: New feature | Status: assigned
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Carlton Gibson):

As small as the change is here, I can't help but thinking it makes little
sense. Async functions just aren't supported in the DTL... and what
purpose do they serve? Adding this auto-wrap in async_to_sync is a road to
where exactly? Nowhere. It's a very short cul-de-sac.

> 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).

If this is a genuine problem (which I'm not sure it is: "Just don't do
that" is often enough) raising an error here would be better. It's not
making a misleading promise that we won't later keep.

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

Django

unread,
Jan 23, 2026, 3:41:39 PM (20 hours ago) Jan 23
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner: Ricardo
| Robles
Type: New feature | Status: assigned
Component: Template system | Version: 6.0
Severity: Normal | Resolution:
Keywords: Template, Async | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Natalia Bidart):

Thanks all for your comments and views! I agree with Carlton in that there
is no async support nowhere in the DTL so adding this specific bit feels
disconnected and strange.
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:13>

Django

unread,
Jan 23, 2026, 3:45:10 PM (20 hours ago) Jan 23
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner: Ricardo
| Robles
Type: New feature | Status: closed
Component: Template system | Version: 6.0
Severity: Normal | Resolution: wontfix
Keywords: Template, Async | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* resolution: => wontfix
* status: assigned => closed

Comment:

I'm convinced. Thanks for helping me keep the bigger picture in mind.
Ricardo, I hope that makes some sense about why we're not acting on this.
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:14>

Django

unread,
3:23 AM (8 hours ago) 3:23 AM
to django-...@googlegroups.com
#36872: Django's template engine cannot handle asynchronous methods
-------------------------------------+-------------------------------------
Reporter: Ricardo Robles | Owner: Ricardo
| Robles
Type: New feature | Status: closed
Component: Template system | Version: 6.0
Severity: Normal | Resolution: wontfix
Keywords: Template, Async | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Ricardo Robles):

Replying to [comment:12 Carlton Gibson]:
> As small as the change is here, I can't help but thinking it makes
little sense. Async functions just aren't supported in the DTL... and what
purpose do they serve? Adding this auto-wrap in async_to_sync is a road to
where exactly? Nowhere. It's a very short cul-de-sac.
>
> > 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).
>
> If this is a genuine problem (which I'm not sure it is: "Just don't do
that" is often enough) raising an error here would be better. It's not
making a misleading promise that we won't later keep.
>
> 🤷

Good morning, the inability to use asynchronous methods in DTL is a real
problem.
There are increasingly more asynchronous libraries that don't require
additional code to convert them to synchronous functionality for use in a
template.

For example, Django 6.0 introduced AsyncPaginator, which cannot be used in
DTL. Why did you add AsyncPaginator if you're not going to allow its use
in DTL?
--
Ticket URL: <https://code.djangoproject.com/ticket/36872#comment:15>
Reply all
Reply to author
Forward
0 new messages