如何防止Django视图在执行时间很长的情况下被重复调用



我有一个Django视图,它运行一个子进程并向用户返回JsonResponse:

def process_images(request, id):
log.debug("Processing images view...")
start = perf_counter()
result = subprocess.run(["ssh", "<REMOTE SERVER>", "bash", "process_images.sh"],
capture_output = True,
text = True) # Run backend processing

log.debug("Result stdout:n" + result.stdout)

with open(f"{settings.MEDIA_ROOT}/{id}/image.json", "r") as f:
response_data = json.load(f)

time_took = perf_counter() - start
log.debug(f"View time took {time_took} seconds")
return JsonResponse(response_data, status=201)

urls.py

from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<id>/process', views.process_images, name='process'),
path('<id>/', views.model, name='model')
]
app_name = "render"

然而,当我尝试访问render/ID/processONCE时,我会收到:

[Oct 25, 2022 07:30:13 PM] DEBUG [render.views:49] Processing images view...
[Oct 25, 2022 07:31:24 PM] DEBUG [render.views:55] Result stdout:
Backend processing...
[Oct 25, 2022 07:31:24 PM] DEBUG [render.views:61] View time took 70.49786422774196 seconds
[Oct 25, 2022 07:31:24 PM] DEBUG [render.views:49] Processing images view...
[Oct 25, 2022 07:32:16 PM] DEBUG [render.views:55] Result stdout:
Backend processing...
[Oct 25, 2022 07:32:16 PM] DEBUG [render.views:61] View time took 52.54661420173943 seconds
[Oct 25, 2022 07:32:16 PM] DEBUG [render.views:49] Processing images view...
[Oct 25, 2022 07:33:08 PM] DEBUG [render.views:55] Result stdout:
Backend processing...
[Oct 25, 2022 07:33:08 PM] DEBUG [render.views:61] View time took 51.900153297930956 seconds

然后它最终返回预期的JsonResponse(显示视图被多次调用(。

然而,如果我减少后端处理,使其更快,然后再次访问它,我只得到以下输出:

[Oct 25, 2022 07:42:41 PM] DEBUG [render.views:49] Processing images view...
[Oct 25, 2022 07:42:44 PM] DEBUG [render.views:55] Result stdout:
Backend processing...
[Oct 25, 2022 07:42:44 PM] DEBUG [render.views:61] View time took 3.0603290796279907 seconds

其中只调用一次(如预期(,并使用适当的JsonResponse。

问题:尽管执行时间很长,但如何确保视图只被调用一次

  • 我宁愿不使用Celery或任何其他库/调度器来帮助离线/异步视图

我看了这个问题,但唯一的答案是针对这个问题的。

虽然我不知道这个错误的来源,但我可以通过使用subprocess.Popen而不是subprocess.run来避免它,这样它就可以在后台运行它并立即返回视图(避免长执行时间(:

def process_images(request, id):
result = subprocess.Popen(["ssh", "<REMOTE SERVER>",
"bash", "process_images.sh"]) # UPDATED LINE   

return JsonResponse({}, status=201)

然后,我使用ajax请求来检查后端处理是否已经完成,并在那里返回结果。

最新更新