【发布时间】:2016-09-10 09:06:18
【问题描述】:
我已经使用 DRF(Django Rest 框架)设置了一个休息 API。 API 功能之一包括创建用户帐户(也称为注册)。
一旦用户被“创建”,我就会向 celery 发送一个任务来发送一封确认邮件。
但是当celery worker执行任务时,出现错误:
DoesNotExist:用户匹配查询不存在。
该任务需要一个用户 ID,仅此而已。然后我尝试打电话给数据库。而正是在这一刻,它失败了。
此时此刻,我很确定用户没有在数据库中创建,因为 create() 方法已经完成。
如果我的任务中有一个 sleep(),它会起作用。
所以我的问题是:
在将任务发送到 Celery 之前,如何确保我的用户已创建到数据库中?
我正在使用 Django 1.9.x
更新 1
tasks.py
@shared_task(name='users.utils.send_activation_email')
def send_activation_email(url, user_id):
try:
user = User.objects.get(id=user_id)
# ...
except User.DoesNotExist:
# handle exception
序列化器.py
def create(self, validated_data):
user_data = validated_data.pop('user')
user = User.objects.create(username=user_data['email'], email=user_data['email'], is_active=False)
user.set_password(user_data['password'])
user.save()
user_profile = user.profile
user_profile.language = get_language() or settings.LANGUAGE_CODE
user_profile.display_name = validated_data['display_name']
user_profile.save()
user_profile.generate_activation_key()
request = self.context['request']
url = request.build_absolute_uri(reverse('user_confirm', kwargs={'activation_key': user.profile.activation_key}))
send_activation_email.delay(url, user.id) # Celery task
subscribe_to_newsletter.delay(user.id, True) # Celery task
return user_profile
更新 2
查看我的设置后,我发现:
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': '*****',
'USER': '*****',
'PASSWORD': '*****',
'HOST': '*****',
'PORT': 5432,
'ATOMIC_REQUESTS': True,
}
}
我禁用了 ATOMIC_REQUESTS,它起作用了!
【问题讨论】:
-
还不够,但我认为您在执行 celery 任务时有未提交的数据。如果您没有在自动提交模式下运行,请确保在将任务传递给 celery 之前提交事务。
-
您可以将注册部分放在任务中,以确保创建用户并在后台发送电子邮件。请注意,在这种情况下,您需要在将任务发送到 celery 之前验证数据(用户名是否唯一)。
-
@e4c5 这正是你说我有未提交的数据时发生的事情。在查看了我的代码后,我注意到我将 ATOMIC_REQUESTS = True 放入了我的数据库配置中。取下它后,它就像一个魅力。
标签: python django django-rest-framework django-celery