首页 > 解决方案 > Django 通过 REST 步骤或处理消息

问题描述

出于学习目的,我想实现下一件事:

例如,我有一个在后台运行 selenium 的脚本,并且我有一些日志消息可以帮助我查看终端中发生了什么。但我想在对 Angular 应用程序的 REST 请求中获得相同的消息。

print('Started')
print('Logged in')
...
print('Processing')
...
print('Success')

在我的 view.py 文件中

class RunTask(viewsets.ViewSet):
queryset = Task.objects.all()

@action(detail=False, methods=['GET'], name='Run Test Script')
def run(self, request, *args, **kwargs):
    task = task()

    if valid['success']:
        return Response(data=task)
    else:
        return Response(data=task['message'])

 def task()
    print('Staring')
    print('Logged in')
    ...
    print('Processing')
    ...
    print('Success')

    return {
        'success': True/False,
        'message': 'my status message'
    }

现在它只显示任务的结果。但我想获得相同的消息来指示前端的进程状态。我无法理解如何组织它。

或者我如何从角度了解我的进程状态?

标签: pythondjangoangulardjango-rest-framework

解决方案


不幸的是,事情并没有那么简单。事实上,REST API 允许您启动任务,但由于它在同一个线程中运行,HTTP 请求将阻塞,直到任务完成后再发送响应。您的print语句不会出现在 HTTP 响应中,而是出现在您的服务器输出中(如果您查看运行的 shell python manage.py runserver,您会看到这些print语句)。

现在,如果您希望实时获得这些输出,则必须寻找 WebSockets。它们允许您在浏览器和服务器之间打开一条“隧道”,并实时发送/接收消息。django-channels 库允许您实现它们。


但是,对于长时间运行的后台任务(如 Selenium 刮刀),我建议查看Celery 任务队列。基本上,您的 Django 进程会将任务安排到队列中。然后,队列中的任务将由一个(或多个!)“工作”进程执行。这样做的好处是您的 Django 进程不会被长任务阻塞:它只是将一些工作添加到队列中然后响应。

当您在队列中添加任务时,Celery 将为您提供此任务的唯一标识符,您可以在 HTTP 响应中返回该标识符。然后,您可以很好地实现另一个端点,该端点在参数中接受任务 id 并返回任务的状态(它是挂起的?完成的?失败的?)。

为此,您必须设置一个“代理”,这是一种存储要执行的任务及其结果的数据库(通常是 RabbitMQ 或 Redis)。芹菜文档很好地解释了这一点:https ://docs.celeryproject.org/en/latest/getting-started/brokers/index.html

无论您选择哪种方式,这都不是一件微不足道的事情,并且需要相当多的工作才能获得一些结果;但有趣的是它如何扩展了经典 HTTP 服务器的可能性。


推荐阅读