diff --git a/AUTHORS b/AUTHORS
index f6d4c5f..783f50b 100644
|
a
|
b
|
answer newbie questions, and generally made Django that much better:
|
| 896 | 896 | rhettg@gmail.com |
| 897 | 897 | Ricardo Javier Cárdenes Medina <ricardo.cardenes@gmail.com> |
| 898 | 898 | ricardojbarrios@gmail.com |
| | 899 | Ricardo Robles Fernández <ricardo.r.f@hotmail.com> |
| 899 | 900 | Riccardo Di Virgilio |
| 900 | 901 | Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com> |
| 901 | 902 | Richard Davies <richard.davies@elastichosts.com> |
diff --git a/django/template/base.py b/django/template/base.py
index d6595e3..d2cd89c 100644
|
a
|
b
|
times with multiple contexts)
|
| 50 | 50 | '<html></html>' |
| 51 | 51 | """ |
| 52 | 52 | |
| | 53 | import asyncio |
| 53 | 54 | import inspect |
| 54 | 55 | import logging |
| 55 | 56 | import re |
| 56 | 57 | import warnings |
| 57 | 58 | from enum import Enum |
| 58 | 59 | |
| | 60 | from asgiref.sync import async_to_sync |
| | 61 | |
| 59 | 62 | from django.template.context import BaseContext |
| 60 | 63 | from django.utils.deprecation import django_file_prefixes |
| 61 | 64 | from django.utils.formats import localize |
| … |
… |
class FilterExpression:
|
| 786 | 789 | if self.is_var: |
| 787 | 790 | try: |
| 788 | 791 | obj = self.var.resolve(context) |
| | 792 | if asyncio.iscoroutine(obj): |
| | 793 | obj = async_to_sync(lambda: obj)() |
| | 794 | |
| 789 | 795 | except VariableDoesNotExist: |
| 790 | 796 | if ignore_failures: |
| 791 | 797 | obj = None |
diff --git a/docs/ref/templates/language.txt b/docs/ref/templates/language.txt
index d80c2f6..f76f4f1 100644
|
a
|
b
|
Use a dot (``.``) to access attributes of a variable.
|
| 94 | 94 | * Attribute or method lookup |
| 95 | 95 | * Numeric index lookup |
| 96 | 96 | |
| 97 | | If the resulting value is callable, it is called with no arguments. The |
| 98 | | result of the call becomes the template value. |
| | 97 | If the resulting value is callable, it is called with no arguments; if it |
| | 98 | is a coroutine, it is awaited using ``async_to_sync()``. The result of |
| | 99 | the call becomes the template value. |
| 99 | 100 | |
| 100 | 101 | This lookup order can cause some unexpected behavior with objects that |
| 101 | 102 | override dictionary lookup. For example, consider the following code |
diff --git a/tests/template_tests/test_base.py b/tests/template_tests/test_base.py
index 33a200c..3cd594e 100644
|
a
|
b
|
class TemplateTests(SimpleTestCase):
|
| 64 | 64 | ) |
| 65 | 65 | |
| 66 | 66 | |
| | 67 | class AsyncTemplateTests(SimpleTestCase): |
| | 68 | def test_async_property_resolution(self): |
| | 69 | from django.template import engines |
| | 70 | |
| | 71 | django_engine = engines["django"] |
| | 72 | |
| | 73 | class Example: |
| | 74 | def sync_method(self): |
| | 75 | return "Synchronous Method Result" |
| | 76 | |
| | 77 | async def async_method(self): |
| | 78 | return "Asynchronous Method Result" |
| | 79 | |
| | 80 | html_string = """ |
| | 81 | <!DOCTYPE html> |
| | 82 | <html> |
| | 83 | <body> |
| | 84 | <p>sync: {{ example.sync_method }}</p> |
| | 85 | <p>async: {{ example.async_method }}</p> |
| | 86 | </body> |
| | 87 | </html> |
| | 88 | """ |
| | 89 | |
| | 90 | template = django_engine.from_string(html_string) |
| | 91 | rendered_html = template.render({"example": Example()}) |
| | 92 | |
| | 93 | self.assertIn("sync: Synchronous Method Result", rendered_html) |
| | 94 | self.assertIn("async: Asynchronous Method Result", rendered_html) |
| | 95 | |
| | 96 | |
| 67 | 97 | class VariableDoesNotExistTests(SimpleTestCase): |
| 68 | 98 | def test_str(self): |
| 69 | 99 | exc = VariableDoesNotExist(msg="Failed lookup in %r", params=({"foo": "bar"},)) |