姜戈 + RabbitMQ + 芹菜。不从视图工作
Django + RabbitMQ + Celery . Not working from views
我有一个 Django 项目
RabbitMQ 是 运行(从命令行测试,它接收消息)
Celery 运行 正在识别任务。
简化的项目树:
├── wha/core
│ ├── wha/core/__init__.py
│ ├── wha/core/celery.py
│ ├── wha/core/settings.py
│ ├── wha/core/urls.py
│ └── wha/core/wsgi.py
├── wha/factura
│ ├── wha/factura/__init__.py
│ ├── wha/factura/admin.py
│ ├── wha/factura/forms.py
│ ├── wha/factura/models.py
│ ├── wha/factura/urls.py
│ └── wha/factura/views.py
└── wha/manage.py
wha/core/init.py
from __future__ import absolute_import
from .celery import app as celery_app
wha/core/celery.py (as docs)
from __future__ import absolute_import
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
from django.conf import settings
app = Celery('core')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
wha/core/settings.py
BROKER_URL = 'amqp://XXX:XXX@localhost:5672//'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_RESULT_BACKEND = "amqp"
CELERY_IMPORTS = ('factura.views')
wha/factura/views.py
@task(name="factura.views.notify")
def notify(request, uid):
factura = get_object_or_404(Factura, pk=uid)
subject = '%s - Your domain' % factura.contrato.dominio.nombre.upper()
from_email = 'Mail Name <asd@asd.com>'
to = [factura.contrato.dominio.cliente.email]
[...] blah blah,发送电子邮件,uid 确实是 "factura" id。我觉得无所谓。
Celery 控制台输出(调试)
-------------- celery@nnbmp.local v3.1.19 (Cipater)
---- **** -----
--- * *** * -- Darwin-15.2.0-x86_64-i386-64bit
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app: core:0x10c451fd0
- ** ---------- .> transport: amqp://hola:**@nnmbp:5672//
- ** ---------- .> results: amqp
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ----
--- ***** ----- [queues]
-------------- .> celery exchange=celery(direct) key=celery
[tasks]
. celery.backend_cleanup
. celery.chain
. celery.chord
. celery.chord_unlock
. celery.chunks
. celery.group
. celery.map
. celery.starmap
. factura.views.notify
URL 用于调用视图:
http://localhost:8000/factura/notify/8
其中 8 是 "factura" id,
编辑:
不起作用的是,当我从浏览器调用 "factura.notify" 时,Celery 无法识别被调用的任务,因此它不会向 RabbitMQ 发送消息。
知道为什么这不起作用吗?
它可能是这一行:
CELERY_IMPORTS = ('factura.views')
这是一个字符串,周围有括号。单元素元组需要逗号:
CELERY_IMPORTS = ('factura.views', )
它不起作用的原因是您 运行 将视图视为 celery 任务,这是完全错误的。您的视图应该通过任务(例如 generate_invoice.delay()
、send_email.delay()
)将一些工作(例如生成 pdf、发送电子邮件)卸载到 Celery,而不是任务本身。
现在 Django 将 url 解析为通知函数(可调用)并简单地同步执行它,因此它不会发布到您的 Celery 消息代理。
这里有一个你可能应该做的例子:
def notify(request, uid):
...
tasks.process_invoice.delay(invoice_id)
return response
@task
def process_invoice(invoice_id):
...
我有一个 Django 项目
RabbitMQ 是 运行(从命令行测试,它接收消息)
Celery 运行 正在识别任务。
简化的项目树:
├── wha/core
│ ├── wha/core/__init__.py
│ ├── wha/core/celery.py
│ ├── wha/core/settings.py
│ ├── wha/core/urls.py
│ └── wha/core/wsgi.py
├── wha/factura
│ ├── wha/factura/__init__.py
│ ├── wha/factura/admin.py
│ ├── wha/factura/forms.py
│ ├── wha/factura/models.py
│ ├── wha/factura/urls.py
│ └── wha/factura/views.py
└── wha/manage.py
wha/core/init.py
from __future__ import absolute_import
from .celery import app as celery_app
wha/core/celery.py (as docs)
from __future__ import absolute_import
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
from django.conf import settings
app = Celery('core')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
wha/core/settings.py
BROKER_URL = 'amqp://XXX:XXX@localhost:5672//'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_RESULT_BACKEND = "amqp"
CELERY_IMPORTS = ('factura.views')
wha/factura/views.py
@task(name="factura.views.notify")
def notify(request, uid):
factura = get_object_or_404(Factura, pk=uid)
subject = '%s - Your domain' % factura.contrato.dominio.nombre.upper()
from_email = 'Mail Name <asd@asd.com>'
to = [factura.contrato.dominio.cliente.email]
[...] blah blah,发送电子邮件,uid 确实是 "factura" id。我觉得无所谓。
Celery 控制台输出(调试)
-------------- celery@nnbmp.local v3.1.19 (Cipater)
---- **** -----
--- * *** * -- Darwin-15.2.0-x86_64-i386-64bit
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app: core:0x10c451fd0
- ** ---------- .> transport: amqp://hola:**@nnmbp:5672//
- ** ---------- .> results: amqp
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ----
--- ***** ----- [queues]
-------------- .> celery exchange=celery(direct) key=celery
[tasks]
. celery.backend_cleanup
. celery.chain
. celery.chord
. celery.chord_unlock
. celery.chunks
. celery.group
. celery.map
. celery.starmap
. factura.views.notify
URL 用于调用视图:
http://localhost:8000/factura/notify/8
其中 8 是 "factura" id,
编辑:
不起作用的是,当我从浏览器调用 "factura.notify" 时,Celery 无法识别被调用的任务,因此它不会向 RabbitMQ 发送消息。
知道为什么这不起作用吗?
它可能是这一行:
CELERY_IMPORTS = ('factura.views')
这是一个字符串,周围有括号。单元素元组需要逗号:
CELERY_IMPORTS = ('factura.views', )
它不起作用的原因是您 运行 将视图视为 celery 任务,这是完全错误的。您的视图应该通过任务(例如 generate_invoice.delay()
、send_email.delay()
)将一些工作(例如生成 pdf、发送电子邮件)卸载到 Celery,而不是任务本身。
现在 Django 将 url 解析为通知函数(可调用)并简单地同步执行它,因此它不会发布到您的 Celery 消息代理。
这里有一个你可能应该做的例子:
def notify(request, uid):
...
tasks.process_invoice.delay(invoice_id)
return response
@task
def process_invoice(invoice_id):
...