Асинхронный HTTP-вызов внутри HTTP-цикла Django Rest Framework - PullRequest
0 голосов
/ 13 сентября 2018

Мне нужно вызвать внешнюю службу для функции get_queryset одного из моих наборов представлений на views.py, но мне не нужно ждать ответа внешней функции.

Как сделать, чтобы следующая строка request.post только что сработала и перешла на следующую строку, не дожидаясь результата?

class SomeViewSet(viewsets.ModelViewSet):
    def get_queryset(self):
        ....
        requests.post(urlOfApi+token)
        .....
        return Some.objects.all()

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Я реализовал конечную точку для запуска фоновой задачи.Когда вы нажимаете post, конечная точка возвращает идентификатор задания.Затем вы можете нажать конечную точку get с идентификатором задачи задания и получить результат или in progress, если задание все еще выполняется.

Я не использовал celery для выполнения этой задачи,но django-q , который я нашел легче, чем сельдерей, и более того, django-q использует все батареи, которые уже есть у django.Вот пример API View, который я реализовал с помощью django-q.

from django.urls import reverse
from django_q.models import Task, OrmQ
from django_q.tasks import async, result
from rest_framework.exceptions import NotFound
from rest_framework.response import Response
from rest_framework.views import APIView


def the_function_to_run():
    # do something here
    pass


class YourTaskApiView(APIView):

    def get(self):

        # you mustr construct the get url to take the id
        task_id = self.kwargs.get('task_id')

        try:
            task = Task.objects.get(id=task_id)
        except Task.DoesNotExist:
            task = None

        # here the task is on processing
        if task:
            return Response({
                'id': task_id,
                'result': result(task_id),
                'started': task.started,
                'stopped': task.stopped,
                'status': 'DONE' if task.stopped else 'RUNNING',
                'success': task.success,
            })
        else:
            # here you find the task in the query (not even processed, but waiting for the cluster to process it)
            for q in OrmQ.objects.all():
                if q.task_id() == task_id:
                    task = q.task()
                    return Response({
                        'id': task['id'],
                        'started': task['started'],
                        'status': 'WAITING', # or ON QUEUE
                        'stopped': None,
                        'success': None,
                    })

        return NotFound()


    def post(self, request):

        # run the task as async
        task_id = async(the_function_to_run)

        # create the reverse for the get so the client already has the link to query for
        # the task status
        link = reverse('yourapp:yournamespace:yourview', kwargs={'task_id': task_id}, request=request)
        return Response(data={'task_id': task_id, 'link': link})
0 голосов
/ 13 сентября 2018

Вам нужно реализовать какие-то фоновые задания для этого вида работы.

Как уже упоминалось в комментарии, одним из способов является использование сельдерея.

Если ты не хочешь пройти через это. Вы можете попробовать следующее:

https://django -background-tasks.readthedocs.io / ен / последний /

Возможно, не такой мощный, как сельдерей, но проще в настройке и запуске.

Вы просто реализуете функцию для выполнения работы (в вашем случае делаете http-запрос к другому сервису), украшаете ее фоновым декоратором. И тогда, в вашем наборе, вы просто вызываете функцию, и она будет запланирована. Вы даже можете выбрать время, когда.

...