You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Celery任务数据库查询返回None/DoesNotExist问题求助

问题

在Django应用中使用Celery任务时,数据库查询出现异常:

  • email_on_assign_reviewer任务遍历reviewerlist查询Reviewer实例时返回None,但视图的perform_create方法中相同查询能正常获取实例,且序列化器已创建对应Reviewer实例。
  • 部分任务查询Submission时抛出DoesNotExist异常。

相关代码如下:

任务代码

@shared_task
def email_on_assign_reviewer(submission, reviewerlist):
    """
    Send an email to the Reviewer when they are assigned to review
    """
    print(submission)   # 输出正常
    print(reviewerlist) # 能完美打印审核员ID列表  
    submission = Submission.objects.get(id=submission)
    print(submission)  # 能完美打印投稿信息  
    
    context = {"some": "context"}
    
    for id in reviewerlist:
        reviewer = Reviewer.objects.filter(id=id).first()
        print(reviewer)  # 这里返回None 
        if reviewer:
            context['reviewer_name'] = reviewer.user.first_name
            utils.sendEmail(
                context,
                template="review_assign.html",
                to=[reviewer.user.email]
            )

视图代码

def perform_create(self, serializer):
    submission = Submission.objects.filter(id=self.kwargs['submission_pk']).first()

    *SOME LOGIC*

    data = serializer.save()
    for i in reviewerlist:
        print(Reviewer.objects.filter(id=i).first())  # 这里能完美打印审核员信息 
    
    tasks.email_on_assign_reviewer.delay(submission.id, reviewerlist)

序列化器代码

def create(self, validated_data):
    submission_id = self.context['submission_id']
    user_ids = validated_data.pop('user_ids', [])
    existing_profile_ids = Somequery.objects.all()
    reviewers_to_create = []
    for user_id in user_ids:
            if user_id not in existing_profile_ids:
                reviewer = Reviewer.objects.create(submission_id=submission_id, user_id=user_id, )
                reviewers_to_create.append(reviewer.pk)
                
    return reviewers_to_create
解决方案

1. 事务未提交导致Celery查询不到数据

视图的perform_create方法中,序列化器创建Reviewer实例后,当前请求的事务可能还未提交就调用了Celery任务。Celery任务独立运行,此时数据库中还没有新创建的Reviewer记录。

  • 解决办法:
    使用Django的transaction.on_commit延迟发送Celery任务,确保事务提交后再执行任务:
    from django.db import transaction
    
    # 在perform_create中替换原任务调用
    transaction.on_commit(lambda: tasks.email_on_assign_reviewer.delay(submission.id, reviewerlist))
    

2. 数据库连接隔离级别问题

如果数据库使用了READ COMMITTED以外的隔离级别,Celery任务可能无法读取到未提交的事务数据。

  • 解决办法:
    确保Django数据库配置的隔离级别为READ COMMITTED(默认配置),在settings.py中:
    DATABASES = {
        'default': {
            # ... 其他配置
            'OPTIONS': {
                'isolation_level': 'read committed',
            },
        }
    }
    

3. Submission查询异常处理

部分任务中Submission.objects.get(id=submission)抛出DoesNotExist,可能是任务执行时数据已被删除或ID无效。

  • 解决办法:
    用filter(...).first()替代get()避免抛出异常,增加容错:
    submission = Submission.objects.filter(id=submission).first()
    if not submission:
        return  # 或记录日志后终止任务
    

4. 确认reviewerlist传递的是正确ID

检查视图中reviewerlist的来源是否为序列化器返回的reviewers_to_create(即Reviewer的ID),而非原始的user_ids,避免传递错误的ID导致查询不到数据。

内容的提问来源于stack exchange,提问作者Ayatoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 02:39:55