Django芹菜任务:新创建的模型DoesNotExist

Mar*_*row 13 django asynchronous celery django-celery

为什么我创建的模型实例,从后来直接启动的芹菜任务中查询,未找到?例如:

# 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
Run Code Online (Sandbox Code Playgroud)

这一切看起来都很好,当然如果我在create()调用后的任何时候查询模型应该存在于数据库中.

更新1:我正在使用transaction.autocommitDjango为我的视图提供的默认行为.

但是下面的任务抛出ObjectDoesNotExist异常:

# app.tasks

class ModelTask(Task):
    def run(self, model_pk):
        from app.models import Model
        Model.objects.get(pk=model_pk)
Run Code Online (Sandbox Code Playgroud)

在我的测试中,正如预期的那样,model_pk是一个正确的正整数ID.

结论

我认为有一些异步/"分开处理"在这里出现的问题,但我不知道它是什么.如果觉得我有一些明显的错误.

我不认为数据库事务是答案,因为Django的默认"自动提交"方法确保在create()调用方法后立即执行数据库操作.

gro*_*pot 10

这些答案需要更新。Django 现在已经transaction.on_commit()为这个确切的问题构建了它,他们甚至提供了一个带有任务的示例:

transaction.on_commit(lambda: some_celery_task.delay('arg1'))
Run Code Online (Sandbox Code Playgroud)

https://docs.djangoproject.com/en/2.1/topics/db/transactions/#django.db.transaction.on_commit


And*_*nyi 7

我的代码中遇到了同样的问题.经过长时间的调查,我发现竞争状况正在发生,因为我正在使用@ transaction.commit_on_success装饰.因此,只有在返回视图后才会提交事务.在我打电话给芹菜任务之后发生了什么.

一旦我删除了"commit_on_success"装饰器,一切都开始按预期工作.因为Django的默认事务行为是在任何数据库更改操作之后提交事务.

您可能还想确保您没有使用TransactionMiddleware,因为它与@ transaction.commit_on_success装饰器类似.如果你想继续使用它,你应该考虑使用@ transaction.autocommit与芹菜的任务,或者你的观点装饰@ transaction.commit_manually.

  • @MarcusWhybrow那么你的视图实际上可能存在于`transaction.commit_on_success`中,你可以检查一下,例如在Django 1.5及更早版本下调用`transaction.is_managed()`吗?例如,Django Admin中的`add_view`包含`commit_on_success`.因此,如果由`add_view`触发的`post_save`信号调用,则您的代码位于托管事务中. (2认同)