【问题标题】:How to return the data from django signal?如何从 django 信号返回数据?
【发布时间】:2021-05-02 05:19:10
【问题描述】:

我正在使用 Django-rest 来开发 API。就我而言,当用户发布数据时,我必须处理发布的数据(需要 2-3 分钟)。我编写了用于预处理数据的 Django 信号。我的 signal.py 文件是这样的,

@receiver(post_save, sender=ExposureIndex)
def calculate_exposure(instance, created, *args, **kwargs):
    ear_table = instance.ear_index.name
    haz_dir = instance.hazard_index.file.path

    # calling celery task
    task = exposure_calculation.delay(ear_table,haz_dir)

    return task.id

而我的芹菜计算函数就在这里,

@shared_task(bind=True)
def exposure_calculation(self, ear_table, haz_dir):
    progress_recorder = ProgressRecorder(self)

    CalculateExposure(ear_table, haz_dir)

    return 'Done'

我的 django-rest 视图函数是这样的,

class ExposureIndexViewSet(viewsets.ModelViewSet):
    queryset = ExposureIndex.objects.all()
    serializer_class = ExposureIndexSerializer
    permission_classes = [permissions.IsAuthenticated]

我的问题是当用户发布数据时,我想返回 task.id 而不是返回实际响应(我试图从 Django 信号中返回它,但它没有在实际 API 中返回)。当用户发布exposureIndexData 时,任何人都可以向我建议如何立即返回task.id

【问题讨论】:

  • 您将无法从信号返回任何内容。相反,您可能需要在 JS 上实现一个加载器,向后端发出请求/等待响应以在任务 ID 准备就绪时获取任务 ID(创建、存储在数据库中或您可以在您的情况下使用的任何其他选项)
  • 这个过程太繁重了,这就是你把它放在芹菜任务中的原因。 http请求和响应是同步的,另一方面任务是异步的。所以无论如何你都不能返回 id。

标签: python django django-rest-framework celery django-signals


【解决方案1】:

我认为您应该覆盖views.py 中的create 方法,而不是创建信号实例。在views.py文件中做这样的事情

class ExposureIndexViewSet(viewsets.ModelViewSet):
    queryset = ExposureIndex.objects.all()
    serializer_class = ExposureIndexSerializer
    permission_classes = [permissions.IsAuthenticated]

    def create(self, request, *args, **kwargs):
        response = super().create(request, *args, **kwargs)
        instance = response.data
        ear_table = instance['ear_table']
        haz_dir = instance['haz_dir']

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)

        task = exposure_calculation.delay(ear_table,haz_dir)

        return Response({'task_id': task.id})

【讨论】:

    【解决方案2】:

    您可以简单地通过您的视图发送响应,而不是使用信号

    def post(self,request):
      #create database manaully
      task=exposure_calculation.delay(ear_table,haz_dir)
      return Response({"message",task.id})
    

    【讨论】:

    • 感谢您的想法。实际上,我必须通过我的views.py 发送回复
    猜你喜欢
    • 1970-01-01
    • 2015-03-01
    • 2016-12-19
    • 2018-05-14
    • 1970-01-01
    • 2021-11-05
    • 2012-01-08
    • 2021-08-18
    • 2011-05-24
    相关资源
    最近更新 更多