2017-02-23 106 views
0

我有+5小时的培训来解释如何:Item.objects.values('type', 'state')返回一个包含只有两个键的字典。django值函数奇怪的行为?

但是Item.objects.values('type', 'state').annotate(nb=Count('id'))工程!

解释器如何知道id属性是否存在,如果它不是由值函数返回?

+0

如果您没有指定'id'字段,我没有看到任何问题,它只会返回您指定的字段,除非您省略字段parameters.Take看看'ValuesIterable'类在https: //github.com/django/django/blob/master/django/db/models/query.py并查看https://docs.djangoproject.com/en/1.10/ref/models/querysets/#中的最后一个示例值。关于你的最后一个问题,它似乎是你试图将'values'用于不同的目的 – chachan

回答

1

它知道id属性存在,因为Item.objects.values('type', 'state')不只是一本字典。这是代表本身作为基于您提供参数的字典的对象。

想象的对象是一张纸,让我们叫它纸A

id : 1 
type : cheese 
state : melted 

你实际上看到的,当你把它是只显示你的相关部分创建的对象的表示,像一张纸孔放在上面的A,纸B

████████████████████ 
████████████████████ 
+--------------------+ 
|type: cheese  | 
+--------------------+ 
+--------------------+ 
|state: melted  | 
+--------------------+ 

但纸A仍然是纸B,完整的下方。这就是为什么Item.objects.values('type', 'state').annotate(nb=Count('id'))工作原理:当annotate去看对象,它要求它实际上,而不是它看起来像一个外部观察员。换句话说,annotate看着纸A,而不是B

通过让对象Item.objects.values('type', 'state')对用户和系统表示不同,它允许系统在需要检查时保留尽可能多的信息。这在ORM模型中很常见,因此数据库和数据库表示之间不会出现差异。

+0

type(Item.objects.values('type','state'))给出了我正在寻找的答案谢谢 – user2080105

1

你的模型具有ID的背景,也Django的ORM知道你的模型定义

Django的ORM的是延迟加载和结果被调用之前,它不会执行任何操作。所以在你调用注释的那一刻,它还不是一个字典,它仍然是对象。在你问它导致目前它触发查询数据库,并返回你的结果

Django的ORM转换成查询这类似于这样

SELECT type, state, count(id) as nb FROM items 
+0

我的问题很简单。如果从一个没有它的字典中调用'id',注释如何可以注释'id' – user2080105

+0

@ user2080105你的模型在后台有id,Django ORM也知道你的模型定义 – iklinac

+0

Django ORM是懒加载的,它不会执行调用结果之前什么也没有。所以在你调用注释的那一刻它还不是一本字典,它仍然是ORM对象 – iklinac

0

数据库中的第一个查询做返回字典有两把钥匙。相反,它返回一个ValuesQuerySet;该查询集的每个元素都是一个字典。

ValuesQuerySet与其他任何查询集一样,保留与模型的连接,因此可以根据需要向查询添加任何其他元素。查询作为一个整体在迭代查询集之前不会执行。