Невозможно запустить задачу сельдерея, которая зависит от кода Django - PullRequest
0 голосов
/ 04 ноября 2019

У меня, похоже, есть сценарий уловки 22 при попытке запустить задачу сельдерея, которая зависит от кода django.

Код сельдерея

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from django.conf import settings
from celery import shared_task
from celery import task
from letters.send_write_letter_reminders import send_write_letter_reminders

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app_name.settings')

app = Celery('app_name')

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')

app.conf.timezone = 'Europe/London'
# Load task modules from all registered Django app configs.
app.autodiscover_tasks(settings.INSTALLED_APPS)

@app.task(bind=True, name='send_letter_reminders')
def send_letter_reminders(slug=None):
    send_write_letter_reminders(slug=slug)

Проблема, с которой я столкнулся, заключается в том, что с этой строкой

from letters.send_write_letter_reminders import send_write_letter_reminders

С ее помощью я получаю:

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

И сервер приложений не будет работать, но без него я получаю:

NameError: name 'send_write_letter_reminders' is not defined

Очевидно, я упускаю что-то фундаментальное в том, как управлять Селери и Джанго вместе, но я не вижу этого. Может кто-нибудь объяснить мне, что я сделал неправильно?

Обновление Я нашел для этого хакерский обходной путь, который включает перемещение импорта в задачу сельдерея. Я понимаю, что это не лучшая практика. Возможно, это поможет объяснить, что происходит.

@app.task(bind=True, name='send_letter_reminders')
def send_letter_reminders(slug=None):
    from letters.send_write_letter_reminders import send_write_letter_reminders
    send_write_letter_reminders.send_write_letter_reminders(slug=slug)

1 Ответ

0 голосов
/ 10 ноября 2019

По сути, вы не можете делать импорт django или импортировать что-либо, что зависит от django, до тех пор, пока вы не выполните строку os.environ.setdefault. Причина, по которой вам не нужно беспокоиться об этом при запуске чего-либо из manage.py, заключается в том, что os.environ.setdefault является первой строкой manage.py. По сути, просто переместите импорт django.conf и letter ниже os.environ.setdefault, и все должно работать лучше. В зависимости от того, какая версия django установлена, вам также может потребоваться явно вызвать django.setup() после установки DJANGO_SETTINGS_MODULE, чтобы завершить настройку django.

...