[英]I'm trying to apply celery to Class based view(apis) in django. How can I do this?
Is it a correct way to apply celery to class based views?将 celery 应用于基于 class 的视图是否正确? And, if it is, how can I apply celery to class based Views?
而且,如果是,我如何将 celery 应用于基于 class 的视图? I can't apply just tagging @app.task above functions inside class.
我不能只在 class 中的函数上方应用标记 @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)
I'm trying to test this api and when I call HTTP GET Method to call this api, i get the error below:我正在尝试测试这个 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'
my celery worker get the task.我的 celery 工人得到了任务。 I think it's not a worker problem..
我认为这不是工人的问题..
In your case might work next scenario.在您的情况下,下一个场景可能会起作用。 Create a task for hard workload:
为繁重的工作量创建一个任务:
@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))
When executed first GET you should create Celery task and then save it TASK_ID somewhere to later get result:第一次执行 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',
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.