'其它进程保存对象后,在Model.objects.filter()之后需要Django transaction.commit()'

2024-05-16 15:24:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个进程运行Django代码库,出于各种原因,一个进程将更新一个对象,如下所示:

myObj.aField = "updated"
myObj.save()

随后,另一个进程尝试读取该对象,如下所示:

^{pr2}$

当从第二个进程读取值时,我不会看到更新的值,而是看到旧值。第二次运行函数时,我确实看到了变化。在

我注意到,如果从第二个进程(读取的那一个)中,我按如下方式更改函数,我将得到更新后的值:

@transaction.commit_manually
def getObj(xxx):
    objs = TheModel.objects.filter(xyz=xxx)
    transaction.commit()
    for obj in objs:
        print obj.aField

在添加了装饰符@transaction.commit_manuallytransaction.commit()行之后,我确实从字段(从另一个进程中保存)中获取更新后的值

有什么理由需要这个吗?使用transaction.commit()对一个实际上根本不更新模型的函数有什么影响/潜在的问题? 我不知道它为什么会起作用,如果它有意义的话,希望有人会遇到这个问题。在

谢谢


Tags: 对象django函数代码obj进程原因xxx
2条回答

因为您使用的是事务中间件,所以每个请求都有一个不同的事务。在

The recommended way to handle transactions in Web requests is to tie them to the request and response phases via Django’s TransactionMiddleware.

It works like this: When a request starts, Django starts a transaction. If the response is produced without problems, Django commits any pending transactions. If the view function produces an exception, Django rolls back any pending transactions.

这意味着,如果第二个进程的请求在写入被触发之前到达,那么它的事务将早于写入。然后,数据库将执行正确的操作并报告创建第二个进程的事务时的当前值。在读取之前手动提交第二个进程的事务是无害的(只要它没有进行任何编辑),并告诉数据库创建一个新的事务。它将在写入日期后写入,因此会给您修改后的结果。在

我也遇到过这个问题。Django缓存查询结果(这对于单个进程来说是件好事)。如果第二个进程具有相同查询的缓存,则在刷新缓存之前,它不会看到更新。在

由于某些原因,transaction.commit()刷新缓存,因此它有助于解决此问题。在运行查询之前调用该方法,应该可以直接从数据库中看到结果。在

相关问题 更多 >