代码之家  ›  专栏  ›  技术社区  ›  iMitwe

使用Django、Cellery和Redis调度任务

  •  1
  • iMitwe  · 技术社区  · 6 年前

    我在芹菜中添加了一个用于数据导出的任务。我希望当用户调用 Export all 按钮,导出任务开始,并且有一个 django消息 显示在前端,而出口继续在后台。但从我的能力来看,我有这个 views.py :

    def CasesPaluExport(request):
        export_cases_palu.delay(request=request)
        messages.success(request, 'CasesPaluExport')
        return JsonResponse({"Ok": "ok"}, safe=False)
    

    这个在 tasks.py :

    def export_cases_palu(request):
        try:
            plaintext = get_template('stock/download_case_palu.txt')
            htmly = get_template('stock/download_case_palu.html')
            d = Context({'username': request.user.username})
    
            subject, from_email, to = 'Download all cases palu', settings.DEFAULT_FROM_EMAIL, request.user.email
            text_content = plaintext.render(d)
            html_content = htmly.render(d)
            msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
            msg.attach_alternative(html_content, "text/html")
            msg.send()
        except:
            logging.warning("Tried to send download email to user {0}".format(request.user))
    

    问题是每当我这么叫的时候 CasesPaluExport 函数,我在 export_cases_palu.delay(request=request) 行:

    Internal Server Error: /user/casepaluexport/
    Traceback (most recent call last):
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
        response = get_response(request)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
        return view_func(*args, **kwargs)
      File "/home/user/project/user/views.py", line 170, in CasesPaluExport
        export_cases_palu.delay(request=request)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/celery/app/task.py", line 413, in delay
        return self.apply_async(args, kwargs)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/celery/app/task.py", line 536, in apply_async
        **options
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/celery/app/base.py", line 737, in send_task
        amqp.send_task_message(P, name, message, **options)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/celery/app/amqp.py", line 554, in send_task_message
        **properties
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/kombu/messaging.py", line 169, in publish
        compression, headers)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/kombu/messaging.py", line 252, in _prepare
        body) = dumps(body, serializer=serializer)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/kombu/serialization.py", line 221, in dumps
        payload = encoder(data)
      File "/usr/lib/python2.7/contextlib.py", line 35, in __exit__
        self.gen.throw(type, value, traceback)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/kombu/serialization.py", line 54, in _reraise_errors
        reraise(wrapper, wrapper(exc), sys.exc_info()[2])
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/kombu/serialization.py", line 50, in _reraise_errors
        yield
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/kombu/serialization.py", line 221, in dumps
        payload = encoder(data)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/kombu/utils/json.py", line 72, in dumps
        **dict(default_kwargs, **kwargs))
      File "/usr/lib/python2.7/json/__init__.py", line 250, in dumps
        sort_keys=sort_keys, **kw).encode(obj)
      File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
        return _iterencode(o, 0)
      File "/home/user/.virtualenvs/project/local/lib/python2.7/site-packages/kombu/utils/json.py", line 62, in default
        return super(JSONEncoder, self).default(o)
      File "/usr/lib/python2.7/json/encoder.py", line 184, in default
        raise TypeError(repr(o) + " is not JSON serializable")
    EncodeError: <WSGIRequest: POST '/user/casepaluexport/'> is not JSON serializable
    [20/Nov/2017 15:47:56] "POST /user/casepaluexport/ HTTP/1.1" 500 186320
    

    这可能表示服务器仍在等待http响应。我怎么解决这个问题?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Daniel Roseman    6 年前

    错误告诉您它无法序列化整个 request 将其发送到任务。

    但是,您在任务本身中从请求中使用的唯一东西是用户对象。您应该只发送用户ID,然后将对象本身放入任务中。

     export_cases_palu.delay(user_id=request.user.id)
    

    ...

    def export_cases_palu(user_id):
        user = User.objects.get(id=user_id)
        d = Context({'username': user.username})
    

    (此外,你不应该把整个任务都放在试一试/除此之外。)

        2
  •  1
  •   Shubhro Shekhar    6 年前

    第一件事:每次在芹菜中添加或删除任何方法时,都必须重新启动芹菜
    第二件事:芹菜在数据库中内部存储(堆栈)方法调用,其参数为JSON对象格式,因此您只能在那里传递JSON可序列化对象,而请求不是JSON可序列化的