鉴于以下Model类:
from django.db import models
class User(models.Model):
friends = models.ManyToManyField('self', symmetrical=False, blank=True)
如果我有一个n个用户的QuerySet,其中至少有一个有两个朋友,并通过朋友ID过滤该QuerySet来检索用户,并对该QuerySet执行.values_list()调用,如下所示: / p>
all_users = User.objects.all()
single_user = User.objects.filter(friends=2)
single_user.values_list('friends', flat=True)
输出结果如下:
>>> [2]
但是如果我在对象的friends字段本身上执行相同的.values_list调用,就像这样:
single_user.first().friends.values_list('id', flat=True)
输出结果为:
>>> [2, 3]
如果在同一个对象上进行这些调用,为什么输出会不同?
作为参考,这是使用Django 1.10和Python 3.5.2
实现的编辑:我想澄清一些困惑。我的问题不在于我误解了查询本身的结果。在这两种情况下,我最终得到了正确的User对象。区别在于一种情况,我得到一个计数1的QuerySet,另一种情况下,我得到了User对象的实例。
所以以不同的方式陈述我的问题:我感到困惑的是如何在相同对象的不同表示上调用values_list会导致不同的输出?
示例,我有以下QuerySet
<QuerySet [<User: John Doe, ID: 1]>
以下对象,每个都有自己的变量
<User: John Doe, ID: 1>
如果我在同一个字段上执行values_list,以必要的方式,我得到两个不同的结果。我想解释为什么。对我来说,我觉得结果应该是一样的。由于它们不是,我对这些事情的运作方式存在误解,并且正在寻求澄清。
答案 0 :(得分:2)
如果您使用ManyToMany关系,则会获得一个新表来存储两个表之间的关系。
id | from_user_id | to_user_id |
1 1 2
2 2 1
3 1 1
4 3 1
User.objects.filter(friends=2)
# return : 1 instances because there are only one 2 in to_user_id column
User.objects.filter(friends=1)
# return : 3 instances
User.objects.filter(friends=3)
# return : 0 instances
single_user.filter(friends=2).values_list('friends', flat=True)
# return : [2]
single_user.filter(friends=2).values_list('id', flat=True)
# return : [1]
#because id 1 User instance has friends which is id 2 as ManyToMany relationship
# this row
id | from_user_id | to_user_id |
1 1 2
single_user.objects.first()
# single_user.objects.first() return first instance in user table. id 1 instance
single_user.objects.first().friends.values_list('id', flat=True)
# return : [2,1]
# id 1 instance has 2 instances in ManytoMany relationship.
# so it returns [2,1]
single_user.objects.last().friends.values_list('id', flat=True)
# return : [1]
# single_user.objects.last() returns id 3
# because I have 1,2,3 instances in User table as example.
# if you see yourapplabel_user_friends table, 3 id instance have 1 id as friends.
答案 1 :(得分:1)
他们是不同的,因为两个查询并不意味着同样的事情!
user.values_list('friends', flat=True)
...返回用户
user.first().friends.values_list('id', flat=True)
...返回'用户'的第一位朋友的朋友的ID。换句话说,您实际上是在这里查找不同用户的朋友。
调试这些内容的一个好方法是查看从查询生成的SQL。这可以帮助您了解Django如何翻译您的查询。
str(user.first().friends.values_list('id', flat=True).query)
VS
str(user.values_list('friends', flat=True).query)
无法读取输出?使用 sqlparse !
sqlparse.format(str(user.first().friends.values_list('id', flat=True).query))