Django过滤器保存QuerySet

时间:2016-09-19 13:44:22

标签: python django django-queryset

我有一个django模型: -

class ModelA(models.Model):
    flag = models.BooleanField(default=True)

接下来,我查询它: -

obj = ModelA.objects.filter(flag=True)

现在,我更改了第一个对象的flag

obj1 = obj[0]
obj1.flag = False
obj1.save()

现在,当我再次获得obj[0]时,它会返回已过滤查询的2nd object。的为什么吗

3 个答案:

答案 0 :(得分:0)

我相信每次运行obj[0]时,Django都会返回数据库并运行查询。您可以使用django.db.connection

查看执行的查询
>>> from django.db import connection

>>> obj = ModelA.objects.filter(flag=True)
>>> print(connection.queries)
[]

>>> o = obj[0]
>>> print(connection.queries)
[{'time': '0.001', 'sql': 'SELECT "myapp_modela"."id", "myapp_modela"."flag" FROM "myapp_modela" WHERE "myapp_modela"."flag" = 1 LIMIT 1'}]

>>> o.flag = False
>>> o.save()
>>> print(connection.queries)
[{'time': '0.001', 'sql': 'SELECT "myapp_modela"."id", "myapp_modela"."flag" FROM "myapp_modela" WHERE "myapp_modela"."flag" = 1 LIMIT 1'},
 {'time': '0.000', 'sql': 'BEGIN'},
 {'time': '0.002', 'sql': 'UPDATE "myapp_modela" SET "flag" = 0 WHERE "myapp_modela"."id" = 1'}]

>>> o = obj[0]
>>> print(connection.queries)
[{'time': '0.001', 'sql': 'SELECT "myapp_modela"."id", "myapp_modela"."flag" FROM "myapp_modela" WHERE "myapp_modela"."flag" = 1 LIMIT 1'},
 {'time': '0.000', 'sql': 'BEGIN'},
 {'time': '0.002', 'sql': 'UPDATE "myapp_modela" SET "flag" = 0 WHERE "myapp_modela"."id" = 1'},
 {'time': '0.000', 'sql': 'SELECT "myapp_modela"."id", "myapp_modela"."flag" FROM "myapp_modela" WHERE "myapp_modela"."flag" = 1 LIMIT 1'}]

答案 1 :(得分:0)

如果你看一下Queryset.__getitem__()(django / db / models / query.py),你会发现这个(django 1.10):

295  qs = self._clone()
296  qs.query.set_limits(k, k + 1)
297  return list(qs)[0]

请注意,如果尚未迭代查询集,您只能到达那里 - 否则它会从它的结果缓存中获取实例,然后您将获得相同的实例两次。

FWIW,这段代码的目的是优化数据库访问(通过在要求单个实例时不提取整个数据集),是的,至少可以说这种行为是非常令人惊讶的。

如果你想要的是保持修改第一个项目,同时仍然将它作为数据集的一部分而你将使用整个数据集,最简单的解决方案是从你的查询集中创建一个list之前:

obj = list(ModelA.objects.filter(flag=True))
obj1 = obj[0]
obj1.flag = False
obj1.save()

答案 2 :(得分:-1)

由于第一个对象不再匹配已过滤的查询集,因此无法在 Allow:GET, HEAD, OPTIONS, TRACE Cache-Control:private Content-Length:5293 Content-Type:text/html; charset=utf-8 Date:Mon, 19 Sep 2016 13:30:09 GMT Server:Microsoft-IIS/8.5 X-Powered-By:ASP.NET X-Powered-By-Plesk:PleskWin 指针中找到它。如果要将查询集克隆到另一个变量,可以使用values_list