У меня проблема с получением доступа к моделям в tasks.py
Моя цель - отправить электронное письмо в различные части приложения (регистрация пользователя, сброс пароля и т. Д.). Для этого я передаю идентификаторы пользователя задаче сельдерея с именем send_email.
@shared_task()
def send_email(sender_id=None, receiver_id=None, type=None, message=None):
sender = User.objects.get(id=sender_id)
receiver = User.objects.get(id=receiver_id)
logger.info("Starting send email")
Email.send_email(sender, receiver, type, message)
logger.info("Finished send email")
Затем задача должна использовать идентификатор, чтобы получить пользователя и отправить ему электронное письмо. Это ломается при попытке импортировать модель User в файл tasks.py.
Я получаю сообщение об ошибке
raise AppRegistryNotReady("Apps aren't loaded yet.") django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
Вещи, которые я пробовал
вызов django.setup () в верхней части файла tasks.py - вызывает
raise RuntimeError("populate() isn't reentrant")
вызывает ту же ошибку, когда помещается в метод send_email. Это были предложения по другим подобным вопросам в SO
Импорт модели в метод 'send_email', позволяет запускать рабочий, но вызывает следующую ошибку
raise AppRegistryNotReady("Apps aren't loaded yet.")
Это было еще одно предложение по аналогичному вопросу в SO
Удаление .delay при вызове функции 'send_email', которая работает (с импортом в верхней части файла tasks.py или в методе send_email), но поскольку задача больше не асинхронная, она не приносит никакой пользы, но, возможно, сужается вниз вопрос?
Примечания?
- Я использую пользовательскую модель, которая расширяет AbstractBaseUser, я видел ряд проблем с github в сельдерее, связанных с этим, но они должны были быть исправлены в сельдерее v3.1 или около того, я полагаю
Я нахожусь на сельдерее v4.1, django 1.11.10, python 2.7 и использую RabbitMQ в качестве брокера и работаю в режиме рабочий / сервер в виртуальной среде. Я начинаю свой рабочий, используя
celery -A api worker -l info
в окне терминала, а затем с помощью терминала pycharm запустить сервер, используя
python manage.py runserver
так эффективно есть 2 envs? Может ли это быть проблемой?
Это может или не быть связано, но для того, чтобы моя пользовательская модель работала в моем app / models.py, у меня есть только одна строка, которая импортирует пользовательскую модель, в противном случае я получаю
django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'myApi.User' that has not been installed
Я попытался установить для модели аутентификации myApi.user.User (пользователь является папкой, в которой объявлена модель, но получает
Invalid model reference 'myApi.user.User'. String model references must be of the form 'app_label.ModelName'.
поэтому я предполагаю, что именно поэтому импорт необходим в myApi / models.py, чтобы его можно было найти здесь?
Структура проекта
├── api
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── celerySettings.py # my celery.py
├── db.sqlite3
├── myApi
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── tasks.py
│ ├── urls.py
│ ├── user
│ │ ├── __init__.py
│ │ ├── managers.py
│ │ ├── models.py
│ │ ├── serializers.py
│ │ ├── urls.py
│ │ └── views.py
│ ├── utils
│ │ └── Email.py
│ ├── views.py
├── manage.py
└── static
tasks.py
from __future__ import absolute_import, unicode_literals
from celery.schedules import crontab
from celery.task import periodic_task
from celery.utils.log import get_task_logger
from celery import shared_task
from celery import current_app
from .user.models import User
from .utils import Email
logger = get_task_logger(__name__)
@shared_task()
def send_email(sender_id=None, receiver_id=None, type=None, message=None):
sender = User.objects.get(id=sender_id)
receiver = User.objects.get(id=receiver_id)
logger.info("Starting send email")
Email.send_email(sender, receiver, type, message)
logger.info("Finished send email")
settings.py
....
INSTALLED_APPS = [
'rest_framework',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'myApi',
'celery',
'rest_framework.authtoken',
'rest_framework.renderers',
]
AUTH_USER_MODEL = 'myApi.User'
CELERY_IMPORTS = ('api.myApi.tasks')
....
celerySettings.py
from __future__ import absolute_import, unicode_literals
from django.conf import settings
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'api.api.settings')
app = Celery('api', broker='amqp://')
# 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(settings, namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
MyAPI / models.py
from user.models import User
MyAPI / admin.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from user.models import User
admin.site.register(User)
апи / wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "api.settings")
application = get_wsgi_application()
Любые предложения будут с благодарностью. Также извините за длинный пост, он мой первый, поэтому я не был уверен, сколько деталей понадобилось.