要更新的实例具有instance.email=abc@mail.com
。
要更新或更改为xyz@mail.com
的电子邮件
UserUpdateSerializer
的更新方法。
def update(self, instance, validated_data):
email_updated=False
email = self.validated_data["email"]
print(instance.email) #abc@email.com
if email!=instance.email:
if User.objects.filter(email=email).exists():
raise serializers.ValidationError("email is not available")
else:
email_updated=True
instance.__dict__.update(**validated_data)
instance.save() # instance is saved.
print(instance.email) #xyz@email.com
if email_updated:
task_send_activation_mail.delay(instance.id)#this one here
print(instance.email) #xyz@email.com
return instance
当我使用celery向用户发送电子邮件时,给该方法的user_id为:
from `celery` import shared_task
@shared_task
def send_activation_mail(user_id):
from project.models import User
user = User.objects.get(pk=user_id)
subject = 'Activate Your '+DOMAIN_SHORT_NAME+' Account'
message = get_template('registration/account_activation_email.html').render({
'domain_url': DOMAIN_URL,
'domain': DOMAIN,
'domain_short_name': DOMAIN_SHORT_NAME,
'domain_full_name': DOMAIN_FULL_NAME,
'domain_email': DOMAIN_EMAIL,
'domain_support_email': DOMAIN_SUPPORT_EMAIL,
'domain_support_url': DOMAIN_SUPPORT_URL,
'mobile_support': MOBILE_SUPPORT,
'user': user,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'token': account_activation_token.make_token(user),
})
user.email_user(subject, DOMAIN_FULL_NAME +' ', html_message=message)
return user.email #"abc@email.com" is printed as celery output.
实例用instance.save()
保存,其中email
从abc@mail.com
更新为xyz@mail.com
,然后实例的ID作为参数传递给{{1} }方法来发送邮件。但是以为电子邮件似乎终于更新了。从shared_task
内部的User
获得的user_id
实例似乎尚未更新,邮件已发送到先前的send_activation_mail(user_id):
。
答案 0 :(得分:0)
validated_data
与self.validated_data
相同吗?
因为我发现您可以互换使用它们
答案 1 :(得分:0)
instance.save()
尚未提交到数据库。在此之前,芹菜任务send_activation_mail.delay(instance.id)
已被调用,导致获取的是比所需的更新实例更早的实例。
因此,要克服这一点,我们应该使用@transaction.atomic
和transaction.on_commit
,即
from django.db import transaction @transaction.atomic def myFunction(): user = User.objects.get(pk=1).update(email="xyz@email.com") transaction.on_commit(lambda: my_task.delay(user.pk))
@transaction.atomic
装饰器将在视图返回时提交事务,或者在视图引发异常时回滚。
transaction.on_commit
是在成功提交所有事务后启动任务的回调。
on_commit
在Django 1.9及更高版本中可用