简体   繁体   English

使用celery发送异步电子邮件不起作用

[英]Asynchronious email sending using celery doesn't work

I'm trying to make Django not to wait until an email is sent. 我试图让Django不要等到发送电子邮件。 I've decided to use Celery to do that. 我已经决定使用Celery来做到这一点。 Unfortunately I can't figure out how to make it work asynchronously. 不幸的是,我无法弄清楚如何使其异步工作。

I've created a file tasks.py : 我创建了一个文件tasks.py

# -*- coding: utf-8 -*-
from __future__ import absolute_import
from .notifications import CustomerNotifications
from celery import shared_task

@shared_task
def prereservation_has_been_confirmed(reservation):
    CustomerNotifications.prereservation_has_been_confirmed(reservation)

The CustomerNotifications.prereservation_has_been_confirmed(reservation) method sends an email to customer. CustomerNotifications.prereservation_has_been_confirmed(reservation)方法向客户发送电子邮件。

Email sending works but it still waits until the email is sent. 电子邮件发送有效,但仍要等到电子邮件发送完毕。 (the view is called by AJAX ). (该视图由AJAX调用)。

Do you know what to do? 你知道该怎么办吗?

EDIT 编辑

This is how the function is being called: 该函数的调用方式如下:

@csrf_exempt
def reservation_confirm(request):
    if request.method == 'POST':
        reservation_id = request.POST.get('reservation_id', False)
        reservation = get_object_or_404(dolava_models.Reservation, id=reservation_id)
        reservation.confirmed = True
        reservation.save()
        tasks.prereservation_has_been_confirmed(reservation)
        return JsonResponse({})
    raise Http404(u'...')

I tried tasks.prereservation_has_been_confirmed.delay(reservation) but it returns that connection has been refused. 我尝试了tasks.prereservation_has_been_confirmed.delay(reservation)但它返回的连接已被拒绝。

SETTINGS.PY - added BROKER_URL = 'django://' , 'kombu.transport.django' and migrated. SETTINGS.PY-添加了BROKER_URL = 'django://' 'kombu.transport.django'并进行了迁移。

# -*- coding: utf-8 -*-

"""
Django settings for dolava project.

Generated by 'django-admin startproject' using Django 1.9.7.

For more information on this file, see
https://docs.djangoproject.com/en/1.9/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.9/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'secret_key'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'admin_interface',
    'flat',
    'colorfield',
    'django.contrib.admin',
    'django.contrib.auth',
    # 'djcelery_email',

    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'dolava_app',
    # 'constance',

    # 'constance.backends.database',
    'solo',
    'django_extensions',
    'django_tables2',
    'django_countries',
    'kombu.transport.django'
]

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

ROOT_URLCONF = 'dolava.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.core.context_processors.media',
            ],
        },
    },
]

WSGI_APPLICATION = 'dolava.wsgi.application'
BROKER_URL = 'django://'

# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')

# CELERY_ALWAYS_EAGER = True
# SMTP SETTINGS
# EMAIL_BACKEND = 'djcelery_email.backends.CeleryEmailBackend'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# EMAIL_BACKEND = "mailer.backend.DbBackend"
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'xxx@gmail.com'
EMAIL_HOST_PASSWORD = 'pass'




MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

[Following the comments] your task was correctly sent to the broker (to the database in your case) you can probably check that your pending task is there. [在注释之后]您的任务已正确发送到代理(对于您的情况是发送到数据库),您可能可以检查您的待处理任务是否在那里。

you don't see anything in the console because you must launch a celery worker that will read all the pending tasks on the broker and will execute them. 您不会在控制台中看到任何内容,因为您必须启动一个celery worker,它将读取代理上的所有待处理任务并执行它们。 have you started the worker process ? 您是否开始了工作进程 there you'll see the tasks that are being called and the results or traceback if something fails 在那里,您将看到正在调用的任务,以及如果失败则返回结果或回溯

You are not making async call to prereservation_has_been_confirmed() in order to delay function execution use prereservation_has_been_confirmed.delay(...) 您不对prereservation_has_been_confirmed()进行异步调用以延迟函数执行,请使用prereservation_has_been_confirmed.delay(...)

@csrf_exempt
def reservation_confirm(request):
    if request.method == 'POST':
        reservation_id = request.POST.get('reservation_id', False)
        reservation = get_object_or_404(dolava_models.Reservation, id=reservation_id)
        reservation.confirmed = True
        reservation.save()

        # change HERE, you are calling your function directly not asynchronously
        tasks.prereservation_has_been_confirmed(reservation)
        # change to below
        # tasks.prereservation_has_been_confirmed.delay(reservation)
        return JsonResponse({})
    raise Http404(u'...')

Other than that, you have not configured Celery properly to use in Django app. 除此之外,您尚未正确配置Celery以在Django应用中使用。 See Django celery first steps 查看Django celery的第一步

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM