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

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

稍后,另一个进程尝试按如下方式读取该对象:
def getObj(xxx):
   objs = TheModel.objects.filter(xyz=xxx)
   for obj in objs:
      print obj.aField

当从第二个进程读取值时,我不会看到更新的值,而是看到旧的值。第二次运行函数时,我确实看到了变化。
我注意到,如果从第二个进程(一个读取)开始,我按如下方式更改函数,就会得到更新的值:
@transaction.commit_manually
def getObj(xxx):
    objs = TheModel.objects.filter(xyz=xxx)
    transaction.commit()
    for obj in objs:
        print obj.aField

在添加decorator@transaction.commit_manuallytransaction.commit()调用下面的filter()行之后,我确实从字段中获得了更新的值(它是从另一个进程中保存的)
有什么必要这样做的原因吗?使用transaction.commit()对一个实际上根本不更新模型的函数有什么影响/潜在问题?
我不确定它为什么会起作用,也不知道它是否有意义,所以希望有人遇到这个问题。
谢谢,

最佳答案

因为您使用的是事务中间件,所以每个请求都会得到不同的事务。
在Web请求中处理事务的推荐方法是通过Django的TransactionMiddleware将它们绑定到请求和响应阶段。
它的工作原理如下:当请求启动时,Django启动一个事务。如果生成的响应没有问题,Django将提交任何挂起的事务。如果view函数产生异常,Django将回滚所有挂起的事务。
这意味着,如果第二个进程的请求在触发写操作之前到达,那么它的事务将早于写操作。然后,数据库将执行正确的操作,并报告在创建第二个进程的事务时的当前值。在读取之前手动提交第二个进程的事务是无害的(只要它没有进行任何编辑),并告诉数据库创建一个新事务。它将在日期后写入,并因此给您修改后的结果。

09-25 20:55