2016-05-14 27 views
0

我已經設置了DRF(Django Rest Framework)的休息API。其中一項API功能包括創建用戶帳戶(a.k.a.註冊)。向Celery發送任務時創建一個用戶給我一個錯誤:用戶匹配查詢不存在

一旦用戶被「創建」,我發送一個任務給芹菜發送確認郵件。

但是,當任務由芹菜工人執行,發生錯誤:

DoesNotExist: User matching query does not exist.

任務需要一個用戶ID,僅此而已。然後我嘗試撥打數據庫。正是在這個時候它失敗了。

在這個確切的時刻,我確信用戶沒有在數據庫中創建,因爲create()方法已經完成。

如果我在我的任務中有一個sleep(),它就可以工作。

所以我的問題是:

我怎樣才能確保發送任務芹菜之前我的用戶創建到DB?

我使用Django 1.9.x的

UPDATE 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 

serializers.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 

UPDATE 2

審查我的設置後,我發現這一點:

DATABASES = { 
    'default': { 
     'ENGINE': 'django.contrib.gis.db.backends.postgis', 
     'NAME': '*****', 
     'USER': '*****', 
     'PASSWORD': '*****', 
     'HOST': '*****', 
     'PORT': 5432, 
     'ATOMIC_REQUESTS': True, 
    } 
} 

我禁用ATOMIC_REQUESTS和它的工作!

+0

沒有足夠的去了,但我認爲你必須執行芹菜任務的時間未提交數據。如果您未在自動提交模式下運行,請確保在將任務傳遞給芹菜之前提交事務。 – e4c5

+0

您可以將註冊部分放入任務中,以確保創建用戶並在後臺發送電子郵件。請注意,在這種情況下,您需要驗證數據(用戶名是唯一的或任何),然後將任務發送到芹菜。 –

+1

@ e4c5這就是當您說我有無限數據時發生的情況。在審查我的代碼後,我注意到我在我的數據庫配置中添加了ATOMIC_REQUESTS = True。去除它後,它就像一個魅力。 – Kornikopic

回答

0

使用Django信號,django.db.models.signals.post_save該模型的save()方法後,將信號發送到接收器被稱爲

from django.contrib.auth.models import User 
from django.db.models.signal import post_save 

def create_user_callback(sender, **kwargs): 
    user = kwargs['instance'] 
    if kwargs['created']: 
     #send email to the user 

post_save.connect(create_user_callback, sender=User) 
相關問題