Django - 间接连接查询

发布于 2025-01-07 21:17:39 字数 746 浏览 0 评论 0原文

如何返回一个间接连接查询,该查询为我提供问题模型中的所有问题。需要注意的是,对于每个问题,我都需要能够访问 UserData 模型。间接关系是 Question -> User 和 User <- UserData (如果可能的话,我不希望更改模型结构)。

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)

编辑:我认为这种关系被认为是“反向关系”。

How can I return an indirect joined query that gives me all of the Questions in the Question model. The caveat, is that for each question, I need to be able to access the UserData model. The indirect relationship is Question -> User and User <- UserData (I prefer not to change the model structure if possible).

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)

Edit: I think this relationship is considered a "reverse relationship".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美煞众生 2025-01-14 21:17:39
Question.objects.select_related('user__userdata').all()

将为每个问题获取 User 对象和 UserData 对象。不支持反向关系除非OneToOne 关系中,就像您所拥有的 (如此处所示

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

will get both the User object and the UserData object for every question. Reverse relationships aren't supported except in OneToOne relationships like you have (As seen here)

薄荷港 2025-01-14 21:17:39

考虑select_lated()

从 3 个查询,到仅使用 select_lated() 的 2 个查询,再到使用 select_lated() 给出更好参数的 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']

有趣的是,您不必调用与 ('user', 'user__userdata') 相关的 select:您可以看到最后一个查询仅使用 '从 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")

Consider select_related().

From 3 queries, to 2 queries with just select_related(), to 1 query with select_related() given better arguments.

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']

It is interresting to note that you don't have to call selected related with ('user', 'user__userdata'): You can see the last query fetches data from the 3 tables with just '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")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文