我有一个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
。的为什么吗
答案 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。