2012-02-20 117 views
0

如何返回一個間接連接的查詢,該查詢爲我提供了問題模型中的所有問題。需要注意的是,對於每個問題,我需要能夠訪問UserData模型。間接關係是問題 - >用戶和用戶< - 用戶數據(如果可能,我不希望更改模型結構)。Django - 間接加入查詢

class Question(models.Model): 
    description = models.CharField(max_length=200) 
    pub_date = models.DateTimeField('date published') 
    image_url = models.CharField(max_length=200) 
    user = models.ForeignKey(User) 

class Answer(models.Model): 
    question = models.ForeignKey(Question) 
    text = models.CharField(max_length=16000) 
    user = models.ForeignKey(User) 

class UserData(models.Model): 
    user = models.OneToOneField(User) 
    access_token = models.CharField(max_length=32) 
    profile_image_url = models.CharField(max_length=200) 

編輯:我認爲這種關係被認爲是「反向關係」。

+0

你也可以發佈一些固定裝置嗎? – jpic 2012-02-20 15:29:07

回答

1

考慮select_related()

從3個查詢到只有select_related()的2個查詢,給出了select_related()給出的更好參數的1個查詢。

In [17]: [q.user.userdata.access_token for q in Question.objects.all()] 
DEBUG (0.000) SELECT "testapp_question"."id", "testapp_question"."description", "testapp_question"."pub_date", "testapp_question"."image_url", "testapp_question"."user_id" FROM "testapp_question"; args=() 
DEBUG (0.000) SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 1 ; args=(1,) 
DEBUG (0.000) SELECT "testapp_userdata"."id", "testapp_userdata"."user_id", "testapp_userdata"."access_token", "testapp_userdata"."profile_image_url" FROM "testapp_userdata" WHERE "testapp_userdata"."user_id" = 1 ; args=(1,) 
Out[17]: [u'1'] 

In [18]: [q.user.userdata.access_token for q in Question.objects.all().select_related()] 
DEBUG (0.000) SELECT "testapp_question"."id", "testapp_question"."description", "testapp_question"."pub_date", "testapp_question"."image_url", "testapp_question"."user_id", "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "testapp_question" INNER JOIN "auth_user" ON ("testapp_question"."user_id" = "auth_user"."id"); args=() 
DEBUG (0.000) SELECT "testapp_userdata"."id", "testapp_userdata"."user_id", "testapp_userdata"."access_token", "testapp_userdata"."profile_image_url" FROM "testapp_userdata" WHERE "testapp_userdata"."user_id" = 1 ; args=(1,) 
Out[18]: [u'1'] 

In [19]: [q.user.userdata.access_token for q in Question.objects.all().select_related('user__userdata')] 
DEBUG (0.000) SELECT "testapp_question"."id", "testapp_question"."description", "testapp_question"."pub_date", "testapp_question"."image_url", "testapp_question"."user_id", "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined", "testapp_userdata"."id", "testapp_userdata"."user_id", "testapp_userdata"."access_token", "testapp_userdata"."profile_image_url" FROM "testapp_question" INNER JOIN "auth_user" ON ("testapp_question"."user_id" = "auth_user"."id") LEFT OUTER JOIN "testapp_userdata" ON ("auth_user"."id" = "testapp_userdata"."user_id"); args=() 
Out[19]: [u'1'] 

據interresting要注意,你不用調用選擇與('user', 'user__userdata')相關的信息:你可以看到的最後一個查詢從表3的數據獲取與只是「user__userdata」:

SELECT 
    "testapp_question"."id", "testapp_question"."description" [...] 
    "auth_user"."id", "auth_user"."username" [...] 
    "testapp_userdata"."id", "testapp_userdata"."user_id" [...] 
FROM 
    "testapp_question" INNER JOIN 
    "auth_user" ON ("testapp_question"."user_id" = "auth_user"."id") LEFT OUTER JOIN 
    "testapp_userdata" ON ("auth_user"."id" = "testapp_userdata"."user_id") 
+0

我讀過,這不適用於像我這樣的反向關係,是對的嗎? – Ryan 2012-02-20 15:27:22

+0

它的工作原理,我剛剛發佈了一個概念證明。 – jpic 2012-02-20 15:32:49

+1

與select相關的確實包含反向關係,因爲UserData.user是一個OneOneField。如果它是外鍵,它將不起作用。 – Alasdair 2012-02-20 16:21:25

2
Question.objects.select_related('user__userdata').all() 

將針對每個問題獲取User對象和UserData對象。不支持反向關係除了OneToOne關係像你有(As seen here

+0

您確定related_name ='userdata'在這裏有用嗎? – jpic 2012-02-20 15:33:11

+0

不,這不是 - 對不起,我剛纔在你評論之前把它從問題中刪除了 - 我忘了它是一個OneToOne,它不需要它 – 2012-02-20 15:37:22