为什么值列表会在Django中保留过滤器?

时间:2017-08-03 21:39:11

标签: python django django-queryset python-3.5

鉴于以下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,以必要的方式,我得到两个不同的结果。我想解释为什么。对我来说,我觉得结果应该是一样的。由于它们不是,我对这些事情的运作方式存在误解,并且正在寻求澄清。

2 个答案:

答案 0 :(得分:2)

如果您使用ManyToMany关系,则会获得一个新表来存储两个表之间的关系。

yourapplabel_user_friends示例

id | from_user_id | to_user_id |
1    1              2  
2    2              1
3    1              1
4    3              1

User.objects.filter(朋友= 2)

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()     
# 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) ...返回用户

的朋友的ID

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))