2017-08-03 69 views
1

下面給出的模型類:爲什麼值列表在Django中保留過濾器?

from django.db import models 

class User(models.Model): 
    friends = models.ManyToManyField('self', symmetrical=False, blank=True) 

如果我有N個用戶,其中至少有一個有兩個朋友一個QuerySet,並通過一個朋友的ID過濾該查詢集檢索用戶和執行.values_list()通話對查詢集,這樣的:

all_users = User.objects.all() 
single_user = User.objects.filter(friends=2) 
single_user.values_list('friends', flat=True) 

結果輸出像這樣:

>>> [2] 

但如果我執行相同.values_li ST調用該對象的朋友域本身,就像這樣:

single_user.first().friends.values_list('id', flat=True) 

結果的輸出:

>>> [2, 3] 

如果這些呼叫被同一對象上進行,原因是輸出有什麼不同?

以供參考,這是使用Django 1.10和Python 3.5.2

編輯實現:我想澄清一些混亂。我的問題不是我誤解了查詢本身的結果。在這兩種情況下,我都會得到正確的用戶對象。不同的是,在一種情況下,我得到了一個計數爲1的QuerySet,在另一箇中我得到了User對象的實例。

所以用不同的方式陳述我的問題:我困惑的是如何調用values_list對象的不同表示中的相同的對象導致不同的輸出?

例子,我有查詢集

<QuerySet [<User: John Doe, ID: 1]> 

而下面的對象之後,各自在自己的變量

<User: John Doe, ID: 1> 

如果我在同場進行values_list,在必要的方式,我得到兩個不同的結果。我想解釋一下爲什麼。對我而言,我感覺結果應該是一樣的。由於他們不是,我誤解了這些事情是如何運作的,我正在尋求澄清。

+0

用戶。修正了錯別字 – Neelik

+0

這是一個解釋一個觀點的例子。這個問題不是關於應該命名什麼模型,而是關於查詢集。感謝您的輸入。 – Neelik

+0

我選擇了單數來希望說明它是一個迭代。在我們的實際代碼中,我們遵循您詳細介紹的指導原則。主要是編輯這個問題,希望能夠提高可讀性。 – Neelik

回答

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. 
+0

謝謝你的回答。在我的情況下,單用戶對象在ManyToManyField中有兩個朋友。但是,當我在實例字段(在本例中爲朋友)上調用values_list時,以及在包含該實例的QuerySet上調用values_list時,它給了我兩個不同的結果。如果我試圖獲取數據的字段是相同的,爲什麼它們的行爲不同?你的答案使用Model類的.objects。我已經過篩選後使用QuerySets。我希望澄清。對不起,長時間評論。 – Neelik

+0

我想檢查你是否完全理解我的答案。我以爲你不明白'single_user.objects.filter(friends = 2).values_list('friends',flat = True)'和'single_user.objects.first()。friends.values_list('id',平=真)'。我給你示例數據和示例返回來讓你理解。 – Jayground

+0

你用'自我'定義了很多東西。你可以認爲from_user_id是用戶,to_user_id是朋友。它可能會讓人感到困惑,因爲它將自己稱爲「自我」,有許多許多領域的定義。 – Jayground

1

他們不同,因爲兩個查詢不意味着同一件事

user.values_list('friends', flat=True) ...返回用戶

user.first().friends.values_list('id', flat=True)朋友的ID的...返回 '用戶'的第一個朋友的朋友的ID。換句話說,你實際上在這裏查找不同的用戶的朋友。調試這樣的事情的


一個好方法,就是看看從查詢生成的SQL。這可以幫助您瞭解Django如何翻譯您的查詢。

str(user.first().friends.values_list('id', flat=True).query) 

str(user.values_list('friends', flat=True).query) 

無法讀取輸出?使用sqlparse

sqlparse.format(str(user.first().friends.values_list('id', flat=True).query)) 
+0

would not user.first()。friends.values_list()返回用戶QuerySet中第一個用戶的朋友的ID列表?在我的情況下,兩個版本都在單個實例上進行操作:一個在QuerySet中,一個在用戶實例中。 – Neelik

+0

雖然QuerySets生成了兩個完全不同的SQL查詢,但我不認爲@ david-lam對它們的解釋是完全正確的。差異似乎確實是一個模型實例還是中間QuerySet的行爲。 –

+0

@ das-g任何想法爲什麼Instance和QuerySet之間的結果不同? – Neelik