为什么我创建的模型实例,从后来直接启动的芹菜任务中查询,未找到?例如:
# app.views
model = Model.objects.create() # I create my lovely model in a view
from app.tasks import ModelTask # I import my Async celery task
ModelTask.delay(model.pk) # I start the task
这一切看起来都很好,当然,如果我在create()
调用之后的任何时候查询模型应该存在于数据库中。
更新1:我正在使用Django为我的视图提供的默认transaction.autocommit
行为。
但是下面的任务抛出了一个ObjectDoesNotExist
异常:
# app.tasks
class ModelTask(Task):
def run(self, model_pk):
from app.models import Model
Model.objects.get(pk=model_pk)
在我的测试中,正如预期的那样,model_pk
是一个正确的正整数ID。
我假设这里出现了一些异步/“单独的过程”问题,但我不知道它是什么。如果觉得我有一些明显的错误。
我不认为数据库事务是答案,因为Django的默认“自动提交”方法确保在调用create()
方法后立即执行DB操作。
我的代码中遇到了同样的问题。经过长时间的调查,我发现种族状况正在发生,因为我正在使用@transaction.commit_on_success装饰。因此,只有在返回视图后才会提交事务。在我打电话给芹菜任务之后发生了什么。
一旦我删除了“commit_on_success”装饰器,一切都开始按预期工作。因为Django的default transaction behavior是在任何数据库更改操作之后提交事务。
您可能还想确保您没有使用TransactionMiddleware,因为它与@transaction.commit_on_success装饰器类似。如果你想继续使用它,你应该考虑在你的视图中使用@transaction.autocommit装饰器与芹菜任务,或@transaction.commit_manually。
这些答案需要更新。 Django现在有transaction.on_commit()
,它是针对这个确切的问题而构建的,它们甚至提供了一个任务示例:
transaction.on_commit(lambda: some_celery_task.delay('arg1'))
https://docs.djangoproject.com/en/2.1/topics/db/transactions/#django.db.transaction.on_commit
由于我的数据库的ATOMIC_REQUEST标志,我遇到了类似的问题。更改配置后:
DATABASES['default']['ATOMIC_REQUESTS'] = False
问题消失了