我有一个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请求来检查后端处理是否已经完成,并在那里返回结果。