sync_to_async 装饰器,Django 中的异步视图

问题描述 投票:0回答:1

我正在尝试按照视频教程并尝试理解 django 中的异步视图和 @sync_to_async 装饰器。

我有这个代码:

import time
import asyncio

from asgiref.sync import sync_to_async
from django.http import HttpResponse

from movies.models import Movie
from stories.models import Story



@sync_to_async
def get_movies_async():
    print('prepare to get the movies...')
    time.sleep(2)
    qs = Movie.objects.all()
    print('got all the movies')


@sync_to_async
def get_stories_async():
    print('prepare to get the stories...')
    time.sleep(5)
    qs = Story.objects.all()
    print('got all the stories')



async def main_view_async(request):
    start_time = time.time()
    await asyncio.gather(get_movies_async(), get_stories_async())
    total = (time.time() - start_time)
    print("total: ", total)
    return HttpResponse('async!')

但是当我从浏览器调用 main_view_async 时,仍然需要 7 秒,而不是像视频教程中那样需要 5 秒。
本教程可能已过时(2020 年)。或者也许我做错了什么?你能帮忙吗?

我的输出

prepare to get the movies...
got all the movies
prepare to get the stories...
got all the stories
total:  7.0126471519470215

教程终端输出

prepare to get the movies...
prepare to get the stories...
got all the movies
got all the stories
total:  5.0126471519470215
django asynchronous
1个回答
0
投票

你是对的,它因为教程是旧的。正如您在 Django 文档 中看到的,在 2020 年底

asgiref
发生了变化:

asgiref 3.3.0 版本更改了默认值 thread_sensitive 参数设置为 True。这是一个更安全的默认值,并且在 很多情况下与 Django 交互都是正确的值,但一定要 如果从之前的 asgiref 更新,则评估sync_to_async()的使用 版本。

这个默认的

thread_sensitive
值可以更改为
False
,但是,我不知道如何使用
@sync_to_async
装饰器来做到这一点,但它可以这样做:


# Change the function to a regular synchronous function
# (removed the decorator and changed the name to make it obvious it's not async)
# @sync_to_async
def get_movies():
    print('prepare to get the movies...')
    time.sleep(2)
    qs = Movie.objects.all()
    print('got all the movies')

# Do the same to this function as what was done to the above function
# @sync_to_async
def get_stories():
    print('prepare to get the stories...')
    time.sleep(5)
    qs = Story.objects.all()
    print('got all the stories')



async def main_view_async(request):
    start_time = time.time()
    
    # Create async functions from the synchronous functions
    # Set the thread_sensitive to False
    get_movies_async = sync_to_async(get_movies, thread_sensitive=False)
    get_stories_async = sync_to_async(get_stories, thread_sensitive=False)

    await asyncio.gather(get_movies_async(), get_stories_async())
    total = (time.time() - start_time)
    print("total: ", total)
    return HttpResponse('async!')
© www.soinside.com 2019 - 2024. All rights reserved.