QuerySet下标将无法按预期工作

时间:2011-04-04 03:47:08

标签: django django-models django-orm

使用过滤器获取QuerySet时,可以使用以下代码轻松进行更改并保存操作:

qs = SomeModel.objects.filter(owner_id=123)
# suppose qs has 1 or many elements
last_login_time = qs[0].last_login_time
qs[0].last_login_time = datetime.now()    # I expect it can assign the new value, but it won't
assertEquals(qs[0].last_login_time, last_login_time)   # YES, it doesn't change
qs[0].save()   #So it won't update the old record

在弄清楚之后,将使用以下代码,它可以正常工作:

qs = SomeModel.objects.filter(owner_id=123)
# suppose qs has 1 or many elements
obj = qs[0]
last_login_time = obj.last_login_time
obj.last_login_time = datetime.now()    # I expect it can assign the new value, but it will
assertNotEquals(obj.last_login_time, last_login_time)   # YES, it does change
obj.save()   #So it will update the old record as expected

我遇到了一些朋友/同事使用第一种方法进行记录更新。而IMO,它很自然,很容易使用。 (当你输入qs [0] 输入obj 时,它们的类型相同)

在阅读完代码(db.models.query)之后,可以找出原因。(当您下载QuerySet时,它将使用qs = self._clone()并且赋值不会发生任何变化)

可能的解决方案:

  1. 进行分配工作 下标QuerySet
  2. 宣布 以上第一种方法是错误的 让用户知道
  3. 所以我想问:

    1. 我的问题是django真正的问题吗?(我想知道为什么django开发人员没有按预期工作)
    2. 您对此问题的建议是什么?对于这样的问题,你最喜欢的方式是什么?

2 个答案:

答案 0 :(得分:0)

使用update更新查询集中的字段。

答案 1 :(得分:0)

我不确定你在这里问的是什么。你是说这是一个bug吗?我不这么认为,它是明确定义的行为:查询集是惰性的,但在迭代或切片时会进行评估。每次切片时,都会得到一个新对象。这是切片本身不会导致非切片查询集被评估的事实的逻辑结果 - 如果结果尚未缓存,切片将仅使用LIMIT 1执行单个数据库调用得到一个结果。否则,你会产生非常不良的副作用。

现在,如果您认为可以在文档中更好地解释这一点,那么欢迎您 - 并且鼓励 - 提交一个错误补丁,以便更好地解释它。