Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit afb4e40

Browse files
add utils to decorate a view with an async middleware
1 parent 11dfb0b commit afb4e40

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

‎django_async_extensions/utils/__init__.py‎

Whitespace-only changes.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
from functools import wraps
2+
3+
from asgiref.sync import async_to_sync, iscoroutinefunction, sync_to_async
4+
5+
6+
def decorator_from_middleware_with_args(middleware_class):
7+
"""
8+
Like decorator_from_middleware, but return a function
9+
that accepts the arguments to be passed to the middleware_class.
10+
Use like::
11+
12+
cache_page = decorator_from_middleware_with_args(CacheMiddleware)
13+
# ...
14+
15+
@cache_page(3600)
16+
def my_view(request):
17+
# ...
18+
"""
19+
return make_middleware_decorator(middleware_class)
20+
21+
22+
def decorator_from_middleware(middleware_class):
23+
"""
24+
Given a middleware class (not an instance), return a view decorator. This
25+
lets you use middleware functionality on a per-view basis. The middleware
26+
is created with no params passed.
27+
"""
28+
return make_middleware_decorator(middleware_class)()
29+
30+
31+
def make_middleware_decorator(middleware_class):
32+
def _make_decorator(*m_args, **m_kwargs):
33+
def _decorator(view_func):
34+
middleware = middleware_class(view_func, *m_args, **m_kwargs)
35+
36+
async def _pre_process_request(request, *args, **kwargs):
37+
if hasattr(middleware, "process_request"):
38+
result = await middleware.process_request(request)
39+
if result is not None:
40+
return result
41+
if hasattr(middleware, "process_view"):
42+
if iscoroutinefunction(middleware.process_view):
43+
result = await middleware.process_view(
44+
request, view_func, args, kwargs
45+
)
46+
else:
47+
result = await sync_to_async(middleware.process_view)(
48+
request, view_func, args, kwargs
49+
)
50+
if result is not None:
51+
return result
52+
return None
53+
54+
async def _process_exception(request, exception):
55+
if hasattr(middleware, "process_exception"):
56+
if iscoroutinefunction(middleware.process_exception):
57+
result = await middleware.process_exception(request, exception)
58+
else:
59+
result = await sync_to_async(middleware.process_exception)(
60+
request, exception
61+
)
62+
if result is not None:
63+
return result
64+
raise
65+
66+
async def _post_process_request(request, response):
67+
if hasattr(response, "render") and callable(response.render):
68+
if hasattr(middleware, "process_template_response"):
69+
if iscoroutinefunction(middleware.process_template_response):
70+
response = await middleware.process_template_response(
71+
request, response
72+
)
73+
else:
74+
response = await sync_to_async(
75+
middleware.process_template_response
76+
)(request, response)
77+
# Defer running of process_response until after the template
78+
# has been rendered:
79+
if hasattr(middleware, "process_response"):
80+
81+
async def callback(response):
82+
return await middleware.process_response(request, response)
83+
84+
response.add_post_render_callback(async_to_sync(callback))
85+
else:
86+
if hasattr(middleware, "process_response"):
87+
return await middleware.process_response(request, response)
88+
return response
89+
90+
if iscoroutinefunction(view_func):
91+
92+
async def _view_wrapper(request, *args, **kwargs):
93+
result = await _pre_process_request(request, *args, **kwargs)
94+
if result is not None:
95+
return result
96+
97+
try:
98+
response = await view_func(request, *args, **kwargs)
99+
except Exception as e:
100+
result = await _process_exception(request, e)
101+
if result is not None:
102+
return result
103+
104+
return await _post_process_request(request, response)
105+
106+
else:
107+
108+
def _view_wrapper(request, *args, **kwargs):
109+
result = async_to_sync(_pre_process_request)(
110+
request, *args, **kwargs
111+
)
112+
if result is not None:
113+
return result
114+
115+
try:
116+
response = view_func(request, *args, **kwargs)
117+
except Exception as e:
118+
result = async_to_sync(_process_exception)(request, e)
119+
if result is not None:
120+
return result
121+
122+
return async_to_sync(_post_process_request)(request, response)
123+
124+
return wraps(view_func)(_view_wrapper)
125+
126+
return _decorator
127+
128+
return _make_decorator

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /