找个地方重写APIView
的dispatch
方法,示例:
apps.common.views.AAPIView
from asgiref.sync import sync_to_async
from rest_framework.views import APIView
class AAPIView(APIView):
"""
Async ApiView
@see
https://github.com/encode/django-rest-framework/pull/8617/commits/79ce07ba9b0d46cb7c0c592ef47e7f834f651df4#diff-b750fc158f144a0a00aab378a20b42038ed6c59f4b80f533331f3c682e76cb06R2
https://github.com/em1208/adrf
"""
async def async_dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
await sync_to_async(self.initial)(request, *args, **kwargs)
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = await handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
def dispatch(self, request, *args, **kwargs):
return self.async_dispatch(request, *args, **kwargs)
在正式使用时,在原有的继承中,额外继承Async APIVIew,示例:
apps.target_manager.views
from asgiref.sync import sync_to_async
import time
from rest_framework import generics
from rest_framework.response import Response
from apps.common.views import AAPIView
from . import serializers as target_serializers
async def test_sleep():
await sync_to_async(time.sleep, thread_sensitive=False)(5)
print('helloworld')
class TargetBaseInfoView(generics.CreateAPIView, AAPIView):
serializer_class = target_serializers.DemoSerializer
async def post(self, request, *args, **kwargs):
asyncio.create_task(test_sleep())
return Response({'method': 'POST'})
apps.target_manager.serializers
from rest_framework import serializers
class DemoSerializer(serializers.Serializer):
urls = serializers.ListField(help_text='待扫描的URL列表')
将数据处理逻辑放在序列化层
from asgiref.sync import sync_to_async
import asyncio
import time
from rest_framework import serializers
async def test_sleep():
await sync_to_async(time.sleep, thread_sensitive=False)(5)
print('helloworld')
class DemoSerializer(serializers.Serializer):
urls = serializers.ListField(
child=serializers.CharField(),
help_text='待扫描的URL列表'
)
def create(self, validated_data):
asyncio.create_task(test_sleep())
return validated_data
from rest_framework import generics
from . import serializers as target_serializers
from apps.common.views import AAPIView
from rest_framework.response import Response
class TargetBaseInfoView(generics.ListCreateAPIView, AAPIView):
serializer_class = target_serializers.DemoSerializer
async def get(self, request, *args, **kwargs):
return Response({'method': 'GET'})
async def post(self, request, *args, **kwargs):
return super().post(request, *args, **kwargs)