目录

1. adrf库基本介绍

2. django2.1. django3.2(此版本只能普通函数实现异步,连接数据库操作不支持异步)2.1.1. 获取代码2.1.2. 编写逻辑1. async_viewsets.py2. serializer3. views.py

2.1.3. 测试

2.2 django4.2及以上2.2.1 daphne启动 同步函数2.2.2 runserver启动同步函数2.2.3 dephne启动异步函数

3. 启动项目3.1. daphne3.2. pycharm配置方式(windows)

1. adrf库

链接: pypi

基本介绍

介绍 Async support for Django REST framework 对 Django REST 框架的异步支持要求 Requirements Python 3.8+ Django 4.1+

2. django

2.1. django3.2(此版本只能普通函数实现异步,连接数据库操作不支持异步)

当前环境不满足条件,所以不能直接使用adrf

2.1.1. 获取代码

新建python虚拟环境(为了获取adrf中的代码,避免把项目环境中的django更新)执行pip install adrf==0.1.3进入adrf的packages,目录如下: 不包含async_viewsets.py,后续会提到。在当前django3.2项目的apps目录下新建adrf文件夹,将另外6个文件复制进去

2.1.2. 编写逻辑

1. async_viewsets.py

文件位置:apps/adrf/async_viewsets.py 在apps/adrf/viewsets.py中已经实现了异步viewsets,但是每次需要继承多个父类比较费劲,直接继承好得了。

from apps.adrf.viewsets import ViewSet as AsyncViewSet

from rest_framework import generics, mixins, views

class AsyncGenericViewSet(AsyncViewSet, generics.GenericAPIView):

# 以后凡是用GenericViewSet的地方都可以用此类替换

pass

2. serializer

文件位置:apps/app1/serializers.py

from apps.adrf.serializers import Serializer as AsyncSerializer

class QASerializer(AsyncSerializer):

"""知识问答历史记录格式"""

role = serializers.CharField(required=True, max_length=32, allow_null=False, allow_blank=False,

help_text='角色')

content = serializers.CharField(required=True, max_length=1024, allow_null=False, allow_blank=False,

help_text='内容')

class Meta:

fields = ['role', 'content']

3. views.py

文件位置:apps/app1/views.py

import asyncio

from asgiref.sync import sync_to_async

from apps.adrf.async_viewsets import AsyncGenericViewSet # 2.1中自己写的

class DataKnowledgeViewSet(mixins.RetrieveModelMixin, AsyncGenericViewSet):

queryset = DataKnowledge.objects.all()

serializer_class = DataKnowledgeModelSerializer

def get_serializer_class(self):

if self.action in ['qa1']:

self.serializer_class = QASerializer

return self.serializer_class

@swagger_auto_schema(operation_description="知识问答",

operation_summary='知识问答',

tags=['知识'],

responses={**SWAGGER_RESPONSE_MESSAGE, 200: 'ok'})

@action(methods=['POST'], detail=False, url_path='qa1', url_name='qa1')

async def qa1(self, request, *args, **kwargs):

serializer = self.get_serializer(data=request.data, many=True)

serializer.is_valid(raise_exception=True)

data = await serializer.adata # data = serializer.data 响应时间差不多

await asyncio.sleep(2)

return Response(data)

@swagger_auto_schema(operation_description="知识问答",

operation_summary='知识问答',

tags=['知识'],

responses={**SWAGGER_RESPONSE_MESSAGE, 200: 'ok'})

@action(methods=['POST'], detail=False, url_path='qa2', url_name='qa2')

async def qa2(self, request, *args, **kwargs):

msg = random.randint(0,99)

await asyncio.sleep(2)

return Response(msg)

@swagger_auto_schema(operation_description="知识问答",

operation_summary='知识问答',

tags=['知识'],

responses={**SWAGGER_RESPONSE_MESSAGE, 200: 'ok'})

@action(methods=['POST'], detail=False, url_path='qa3', url_name='qa3')

def qa3(self, request, *args, **kwargs):

msg = random.randint(0, 99)

return Response(msg)

2.1.3. 测试

不能用requests测不出来。。

import time

import asyncio

import aiohttp

import json

async def fetch(session):

payload = json.dumps([

{

"role": "user",

"content": "dsm出现了红色错误"

}

])

headers = {

'Content-Type': 'application/json'

}

url1 = "http://127.0.0.1:8001/cn/api/data-knowledge/qa1/"

url2 = "http://127.0.0.1:8001/cn/api/data-knowledge/qa2/"

url3 = "http://127.0.0.1:8001/cn/api/data-knowledge/qa3/"

async with session.post(url1, data=payload, headers=headers) as response:

return await response.text()

async def xxx():

async with aiohttp.ClientSession() as session:

html = await fetch(session)

print(html)

async def main(req_count=10):

tasks = []

for i in range(0, req_count):

task = asyncio.create_task(xxx())

tasks.append(task)

await asyncio.wait(tasks)

# 运行异步任务

x1 = time.time()

loop = asyncio.get_event_loop()

loop.run_until_complete(main())

x2 = time.time()

print(x2 - x1)

###结果

# url1

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

{"message":"OK","code":200,"results":[{"role":"user","content":"dsm出现了红色错误"}]}

2.2377092838287354

# url2

{"message":"OK","code":200,"results":92}

{"message":"OK","code":200,"results":95}

{"message":"OK","code":200,"results":55}

{"message":"OK","code":200,"results":64}

{"message":"OK","code":200,"results":13}

{"message":"OK","code":200,"results":81}

{"message":"OK","code":200,"results":83}

{"message":"OK","code":200,"results":28}

{"message":"OK","code":200,"results":2}

{"message":"OK","code":200,"results":8}

2.2307043075561523

# url3同步函数正常返回

2.2 django4.2及以上

连接数据库自带异步???adrf存在的意义?

普通函数还是可以通过adrf进行异步返回

async def qa2(self, request, *args, **kwargs):

msg = random.randint(0,99)

await asyncio.sleep(2)

return Response(msg)

2.2.1 daphne启动 同步函数

ModelSerializer

def retrieve(self, request, *args, **kwargs):

return super().retrieve(request, *args, **kwargs)

单个请求:0.8s 50个请求:2.4s

2.2.2 runserver启动同步函数

ModelSerializer

def retrieve(self, request, *args, **kwargs):

return super().retrieve(request, *args, **kwargs)

1个请求:0.8s 50个请求:1.8s

2.2.3 dephne启动异步函数

AsyncModelSerializer

async def retrieve(self, request, *args, **kwargs):

instance = await self.aget_object()

serializer = self.get_serializer(instance)

data = await serializer.adata

return Response(data)

单个请求:0.8s 50个请求:2.4s

3. 启动项目

runserver开发阶段支持异步,如果想同步那么把下面INSTALLED_APPS 中的daphne注释

3.1. daphne

安装:pip install daphne

配置:settings.py

INSTALLED_APPS = [

...

'daphne', # 需要靠前位置

...

]

...

ASYNC_MODE = 'django' # 不知道啥用

ASGI_APPLICATION = 'service_brain_model.asgi.application'

启动:daphne service_brain_model.asgi:application -h 0.0.0.0 -p 8001

3.2. pycharm配置方式(windows)

如有问题欢迎指正

好文阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。