Skip to content

Commit e0864c1

Browse files
committed
document utils to decorate a view with an async middleware
1 parent afb4e40 commit e0864c1

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

docs/middleware/base.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ with the following specification:
1212
```
1313
where `get_response` is an **async function**, sync functions are not supported and **will raise** an error.
1414

15+
**Note:** you can use middlewares drove from this base class with normal django middlewares, you can even write sync views
16+
`get_response` is usually provided by django, so you don't have to worry about it being async.
17+
1518
----------------------------
1619

1720
other methods are as follows:

docs/middleware/decorate_views.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
`django_async_extensions.utils.decorators.decorator_from_middleware` and
2+
`django_async_extensions.utils.decorators.decorator_from_middleware_with_args`
3+
are provided to decorate a view with an async middleware directly.
4+
5+
they work almost exactly like django's [decorator_from_middleware](https://docs.djangoproject.com/en/5.1/ref/utils/#django.utils.decorators.decorator_from_middleware)
6+
and [decorator_from_middleware_with_args](https://docs.djangoproject.com/en/5.1/ref/utils/#django.utils.decorators.decorator_from_middleware_with_args)
7+
but it expects an async middleware as described in [AsyncMiddlewareMixin](base.md)
8+
9+
**Important:** if you are using a middleware that inherits from [AsyncMiddlewareMixin](base.md) you can only decorate async views
10+
if you need to decorate a sync view change middleware's `__init__()` method to accept async `get_response` argument.
11+
12+
with an async view
13+
```python
14+
from django.http.response import HttpResponse
15+
16+
from django_async_extensions.middleware.base import AsyncMiddlewareMixin
17+
from django_async_extensions.utils.decorators import decorator_from_middleware
18+
19+
class MyAsyncMiddleware(AsyncMiddlewareMixin):
20+
async def process_request(self, request):
21+
return HttpResponse()
22+
23+
24+
deco = decorator_from_middleware(MyAsyncMiddleware)
25+
26+
27+
@deco
28+
async def my_view(request):
29+
return HttpResponse()
30+
```
31+
32+
33+
if you need to use a sync view design your middleware like this
34+
```python
35+
from django_async_extensions.middleware.base import AsyncMiddlewareMixin
36+
37+
from asgiref.sync import iscoroutinefunction, markcoroutinefunction
38+
39+
40+
class MyMiddleware(AsyncMiddlewareMixin):
41+
sync_capable = True
42+
43+
def __init__(self, get_response):
44+
if get_response is None:
45+
raise ValueError("get_response must be provided.")
46+
self.get_response = get_response
47+
48+
self.async_mode = iscoroutinefunction(self.get_response) or iscoroutinefunction(
49+
getattr(self.get_response, "__call__", None)
50+
)
51+
if self.async_mode:
52+
# Mark the class as async-capable.
53+
markcoroutinefunction(self)
54+
55+
super().__init__()
56+
```

0 commit comments

Comments
 (0)