Python中如何在Django的view中阻塞请求

具体如图中,一个是验证码,一个验证码颜色,https://gitee.com/zhuqiyu/django_monitor/blob/master/index_img/index.png
目前是让验证码颜色函数阻塞 0.01 秒,但是有时候验证码函数超过 0.01 秒就会导致第二张图片加载不出来
代码地址 https://gitee.com/zhuqiyu/django_monitor/blob/master/monitor/ad/views.py (auth 是验证码函数,auth2 是验证码颜色函数)
代码
auth_code_color = None
def auth(request):
“”" 验证码函数 ,authCode 类来自 Authcode.py
@:return
auth_code_img, 二进制图片
“”"
auth_code = authCode()
auth_code_img = auth_code.gene_code()
auth_code_text = auth_code.text
global auth_code_color
auth_code_color = auth_code.create_color()
request.session[“verify_code”] = auth_code_text
return HttpResponse(auth_code_img, ‘image/png’)
def auth2(request):
time.sleep(0.01)
global auth_code_color
return HttpResponse(auth_code_color, ‘image/png’)
Python中如何在Django的view中阻塞请求


7 回复

请问能用什么方式将 time.sleep(0.01)替换了吗,或者思路也行。之前在 auth 函数中添加一个变量,值为 1,在 auth2 中-1,可能实现的有问题,结果比现在还差。


在Django的view中,你可以通过几种方式实现请求的“阻塞”,这通常指的是让请求处理暂停一段时间,或者等待某个条件满足。最常见的方法是使用time.sleep(),但更符合Web应用场景的做法是使用异步等待。

1. 使用time.sleep(简单阻塞) 这是最直接的方法,但会阻塞整个工作线程,不推荐在生产环境中对耗时操作使用。

import time
from django.http import HttpResponse

def my_view(request):
    # 阻塞5秒
    time.sleep(5)
    return HttpResponse("请求处理完成,已阻塞5秒")

2. 使用asyncio.sleep(异步视图,推荐) 如果你使用的是Django 3.1+并启用了异步支持,可以使用异步视图,这样在等待时不会阻塞其他请求。

import asyncio
from django.http import HttpResponse

async def my_async_view(request):
    # 异步等待5秒,不会阻塞服务器线程
    await asyncio.sleep(5)
    return HttpResponse("异步请求处理完成,已等待5秒")

3. 等待某个条件(轮询) 如果需要等待某个外部条件满足,比如一个任务完成,可以使用轮询的方式。

import time
from django.http import HttpResponse, HttpResponseBadRequest

def waiting_view(request):
    task_id = request.GET.get('task_id')
    if not task_id:
        return HttpResponseBadRequest("需要task_id参数")

    # 模拟等待某个任务完成,最多等待10秒
    timeout = 10
    start_time = time.time()
    while not is_task_completed(task_id):  # 假设的检查函数
        if time.time() - start_time > timeout:
            return HttpResponse("等待超时", status=408)
        time.sleep(0.5)  # 每次检查间隔0.5秒

    return HttpResponse(f"任务 {task_id} 已完成")

# 假设的任务完成检查函数
def is_task_completed(task_id):
    # 这里应该是你的业务逻辑,检查任务状态
    # 例如从数据库或缓存中查询
    # 此处返回True仅作示例
    return True

关键点:

  • time.sleep() 在同步视图中会阻塞整个工作线程,这意味着在此期间,该线程无法处理其他请求。这可能会严重影响服务器的并发能力,特别是在使用同步工作模式(如Gunicorn的同步worker)时。仅适用于本地测试或极低并发场景。
  • 异步等待 (asyncio.sleep) 是更优的选择。在异步视图中,await asyncio.sleep() 会将控制权交还给事件循环,允许事件循环去处理其他异步任务(如其他请求),从而实现“非阻塞”的等待。这是处理需要等待的I/O密集型操作的现代方式。
  • 轮询等待条件 适用于需要等待外部事件(如后台任务完成、第三方API回调)的场景。重要的是要设置超时机制,避免请求无限期挂起,并合理设置检查间隔,避免过于频繁的检查消耗资源。

总结建议:对于需要等待的视图,优先使用Django的异步支持。

目前最容易出现的是在服务重启之后的前两次访问,后面就一般不会复现。

为什么不在第一个请求结束后再发起第二个请求啊

因为我不会前端。。

<div style=“display: inline-block;”><img name=“img_code” src="/ad/auth/?0.42844671870369355" onclick=“this.src=’/ad/auth/?’+Math.random();document.getElementById(‘verify_code_color’).src=’/ad/auth2/?’+Math.random()”/></div>
<div style=“position: absolute;left: 90px;top: 10px;”>输入 <img id=“verify_code_color” src="/ad/auth2/?0.42844671870369355"/> 验证码</div>

别瞎折腾了百度一下 django-captcha
你自己写的那个 login 也是乱七八糟的,还不直接 django 自己带的 auth 模块呢。

回到顶部