Я пытаюсь применить сельдерей к классу (apis) в django. Как я могу это сделать? - PullRequest
1 голос
/ 13 апреля 2020

Это правильный способ применения сельдерея в классовых представлениях? И, если это так, как я могу применить сельдерей к представлениям на основе классов? Я не могу применить только тегирование @ app.task над функциями внутри класса.

class ScheduleByFranchiseIdView(generics.RetrieveAPIView):
permission_classes = (IsAdmin,)
serializer_class = ScheduleSerializer
@app2.task
def get(self, request, franchise_id, start = None, end = None):
    if start != None and end != None:
        query1 = Q(student__profile__franchise__exact=franchise_id)
        query2 = Q(start_time__gte=start)
        query3 = Q(end_time__lt=end)
        queryset = Schedule.objects.filter(query1 & query2 & query3).exclude(status=ScheduleStatus.DELETED).order_by('-id')
        serializer = ScheduleSerializer(queryset, many=True)
    else:
        query1 = Q(student__profile__franchise__exact=franchise_id)
        queryset = Schedule.objects.filter(query1).exclude(status=ScheduleStatus.DELETED).order_by('-id')
        serializer = ScheduleSerializer(queryset, many=True)

    return Response(serializer.data)

Я пытаюсь проверить этот API, и когда я вызываю метод HTTP GET для вызова этого API, я получаю ошибку ниже :

Traceback (most recent call last):
  File "C:\Users\Tonyscoding\Desktop\TOCOL\TOCOL_backend\api\testing\test_pagination.py", line 154, in test_admin_schedule_pagination
    response = self.client.get('/api/schedule/by/franchise/simple/1/')
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\test.py", line 286, in get
    response = super().get(path, data=data, **extra)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\test.py", line 203, in get
    return self.generic('GET', path, **r)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\test.py", line 232, in generic
    method, path, data, content_type, secure, **extra)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\django\test\client.py", line 422, in generic
    return self.request(**r)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\test.py", line 283, in request
    return super().request(**kwargs)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\test.py", line 235, in request
    request = super().request(**kwargs)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\django\test\client.py", line 503, in request
    raise exc_value
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\django\views\generic\base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\views.py", line 476, in raise_uncaught_exception
    raise exc
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\rest_framework\views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\celery\local.py", line 191, in __call__
    return self._get_current_object()(*a, **kw)
  File "C:\Users\Tonyscoding\Desktop\TOCOL\venv\lib\site-packages\celery\app\task.py", line 392, in __call__
    return self.run(*args, **kwargs)
TypeError: get() missing 1 required positional argument: 'request'

мой сельдерей получил задание. Я думаю, что это не проблема рабочего ..

1 Ответ

0 голосов
/ 16 апреля 2020

В вашем случае может сработать следующий сценарий. Создайте задачу для тяжелой рабочей нагрузки:

@app.task
def schedule_by_franchise(franchise_id, start=None, end=None):
    # Do some slow workload, filtering by non-indexed fields or something.
    if start is not None and end is not None:  # is not None ~20% faster than != None
        query1 = Q(student__profile__franchise__exact=franchise_id)
        query2 = Q(start_time__gte=start)
        query3 = Q(end_time__lt=end)
        queryset = Schedule.objects.filter(query1 & query2 & query3).exclude(status=ScheduleStatus.DELETED).order_by('-id')
    else:
        query1 = Q(student__profile__franchise__exact=franchise_id)
        queryset = Schedule.objects.filter(query1).exclude(status=ScheduleStatus.DELETED).order_by('-id')

    # Returns something serializable and what could be used for more faster DB search (founded object primary keys might fits)
    return tuple(queryset.values_list('id', flat=True))

При первом выполнении GET вы должны создать задачу Celery, а затем сохранить ее TASK_ID где-нибудь, чтобы позже получить результат:

from celery.result import AsyncResult


class ScheduleByFranchiseIdView(generics.RetrieveAPIView):
    permission_classes = (IsAdmin,)
    serializer_class = ScheduleSerializer

    def get(self, request, franchise_id, start=None, end=None, task_id=None):
        if not task_id:
            task = schedule_by_franchise.delay(franchise_id, start, end)
            return Response({
                'task': task.task_id,
                'status': 'processing',
                'message': f'Please, try again in 10 seconds with following task_id={task.task_id}',
            })
        else:
            result = AsyncResult(task_id)
            if result.ready():
                ids = result.result
                queryset = Schedule.objects.filter(id__in=ids)
                serializer = ScheduleSerializer(queryset, many=True)
                return Response(serializer.data)
            else:
                return Response({
                    'status': 'not_ready_yet',
                    'message': 'Please, try again in 5 seconds',
                })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...