先决条件
项目环境依赖
Python >= 3.8
Django >= 3.1
Uvicorn
ASGI
ASGI支持异步服务器网关接口。ASGI与WSGI向后兼容,可以直接将uWSGI之类的WSHI服务器切换至Uvicorn或Daphne之类的ASGI服务器。
创建项目与应用
mkdir django-async-views && cd django-async-views
python3.8 -m venv env
source env/bin/activate
alias activate='source 绝对路径'(添加/etc/profile永久生效)
# 退出虚拟环境 deactivate
django-admin.py startproject hello_async
1
2
3
4
5
6
安装Uvicorn并启动
pip install uvicorn
使用Uvicorn运行项目,需要从项目跟目录使用命令:
uvicorn (project_name).asgi:application --reload(--reload标志告诉uvicorn监视文件的更改,发现更改从新加载)
本项目为例:
uvicorn hello_async.asgi:application
1
2
3
4
5
##异步使用
views.py
import asyncio
from time import sleep
import httpx
from django.http import HttpResponse
# 异步任务
async def http_call_async():
for num in range(1, 6):
await asyncio.sleep(1)
print(num)
async with httpx.AsyncClient() as client:
r = await client.get("https://httpbin.org/")
print(r)
# 同步任务
def http_call_sync():
for num in range(1, 6):
sleep(1)
print(num)
r = httpx.get("https://httpbin.org/")
print(r)
# 异步视图 - 无异步或同步任务
async def index(request):
return HttpResponse("Hello, async Django!")
# 异步视图 - 调用异步任务
async def async_view(request):
loop = asyncio.get_event_loop()
loop.create_task(http_call_async())
return HttpResponse("Non-blocking HTTP request")
# 同步视图 - 调用普通同步任务
def sync_view(request):
http_call_sync()
return HttpResponse("Blocking HTTP request")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
urls.py
# hello_async/urls.py
from django.contrib import admin
from django.urls import path
from hello_async.views import index, async_view, sync_view
urlpatterns = [
path("admin/", admin.site.urls),
path("async/", async_view),
path("sync/", sync_view),
path("", index),
]
1
2
3
4
5
6
7
8
9
10
11
12
13
Django中异步视图中调用和执行异步任务是非阻塞的,执行效率非常高。如果在异步视图中调用同步任务是与同步视图执行同步任务无区别。当你希望使用Django异步视图提升你的代码效率时,不仅视图需要是异步的,其调用的任务函数也必须是异步的。
同步转异步
异步视图内调用同步任务(比如通过Django ORM与数据库进行交互),请使用sync_to_async作为包装器或装饰器。
from asgiref.sync import sync_to_async
async def async_with_sync_view(request):
loop = asyncio.get_event_loop()
async_function = sync_to_async(http_call_sync)
loop.create_task(async_function())
return HttpResponse("Non-blocking HTTP request (via sync_to_async)")
————————————————
版权声明:本文为CSDN博主「海...」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43580523/article/details/122038406