我正在努力学习视频教程,并try 理解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!')

But when I call main_view_async from my browser it still takes 7 seconds, not 5 seconds like in the video tutorial.
The tutorial might be outdated (year 2020). Or perhaps I am doing something wrong? Can you please help?

My output

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

The tutorial terminal output

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

推荐答案

你是对的,它是is,因为教程是旧的.正如你在Django docs中看到的那样,在2020年底,asgiref发生了变化:

asgiref 3.3.0版更改了 thread_sensitive参数为True.这是一个更安全的默认值, 在许多情况下,与Django交互时会使用正确的值,但请确保 如果从先前的更新asgiref,则判断sync_to_blog()的使用 版本.

可以将这个默认的thread_sensitive值更改为False,但是,我不知道如何使用@sync_to_async修饰器来实现这一点,但can可以这样完成:


# Change the function to a regular synchronous function
# Removed the decorator and
# Changed the name to make it obvious it's not async function
# @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!')

Django相关问答推荐

使用django直接计算geohash而不创建模型

Django Model邮箱字段是必需的,即使在我将其设置为NULL=True和BLACK=True之后也是如此

Django REST序列化程序TO_REATION失败

通过 B 的外键列表访问模型 B 的行

当前路径 **/POST 与其中任何一个都不匹配

如何在Django管理自定义筛选器中包含自定义模型方法?

django - 表单没有错误,但 form.is_valid() 没有验证

使用基于类的 UpdateView 在 Django 中更新用户模型

如何在 django 中生成 url

Django 基于角色的视图?

在 Django 管理屏幕中删除添加另一个

如何在 django-rest-framework 中为 API 使用 TokenAuthentication

如何验证对象是否存在于多线程中

Django:如何编写查询以使用多列进行排序,通过模板显示

Django 国际化语言代码

Django ALLOWED_HOSTS IP 范围

django 静态文件版本控制

如何查询名称包含python列表中任何单词的模型?

Django 1.7 - 如何 suppress (1_6.W001)某些元素单元测试可能无法按预期执行.?

在 Django 中的字段中添加额外的约束