如何访问反向关系django的反向关系

Posted

技术标签:

【中文标题】如何访问反向关系django的反向关系【英文标题】:How to access the a reverse relation of a reverse relation django 【发布时间】:2018-07-05 08:49:38 【问题描述】:

我决心尝试让所有其他用户回复与给定回复相同的评论。我想出了以下 python,但我担心这会做不止一个 DB 调用。

other_repliers = [other_reply.user for other_reply in my_reply.comment.replies.filter()]

我正在寻找一个单分贝调用修复程序。 Psuedo-SQL 逻辑类似于:

SELECT u.*
FROM users AS u
INNER JOIN replies AS r 
   ON r.user = user.id  
WHERE r.comment = my_reply.comment
AND r.user != my_reply.user

有人知道我可以在 python django 命令链中执行上述 SQL 的方法吗?


编辑: 当你忽略任何不是关系的东西时,我的模型看起来像这样:

class Comment(models.Model):
    user = models.ForeignKey(User, related_name='comments')
    listing = models.ForeignKey(Listing, related_name='comments')

class CommentReply(models.Model):
    user = models.ForeignKey(User, related_name='replies')
    comment = models.ForeignKey(Comment, related_name='replies')

class User(models.Model):
     pass

编辑:我希望在下图中收集最后一列:

         /--- r4 --- u4
        /
r1 --- c1 --- r3 --- u3
        \
         \--- r2 --- u2
          *
           ** r1  

其中 r* 是请求,c* 是 cmets,u* 是用户 星号线表示 r1 被忽略(因为它用于查找其他 r*s)。

【问题讨论】:

你能提供你的模型定义吗? 我已经剥离(我假设的)不相关的字段。如果您认为我遗漏了解决此问题的关键内容,请说出来。 print(my_reply.comment.replies.filter().query) 查看 django 是如何编写查询的。 Django Debug Toolbar 还可以让您分析所有发出的 sql。 嘿@cowbert 这真的很酷(一直想知道如何访问 SQL 查询),但这只能告诉我我能做什么。不是我打算做的?我在这里错过了什么吗? 它会告诉你 django 正在生成什么,这将帮助你弄清楚你需要在模型中改变什么来优化它。 【参考方案1】:

你也可以使用select_related():

replies_with_users = CommentReply.objects.filter(comment_id=my_reply.comment_id) \
                                         .exclude(user=my_reply.user) \
                                         .select_related('user')

users = [reply.user for reply in replies_with_users]

这使用连接来检索单个查询中的所有用户。列表推导只是将那些已经检索到的用户重新打包成您的用例所需的格式。

旁注:如果您担心检索(但不使用)可能很大的评论正文,您可以随时将.defer('body_field_name') 粘贴到查询中。您还可以使用双下划线表示法延迟用户未使用的字段(如果需要)。

【讨论】:

【参考方案2】:

我不确定是否可以使用 django-API 进行单个查询,但应该可以使用两个查询。你的共同元素是Comment。首先让我们得到所有回复 r1, r2, r3, r4, ... 对这个评论:

all_replies = CommentReply.objects.filter(comment=my_reply.comment)

现在我们只需要这些回复中的用户

users = User.objects.filter(replies__in=all_replies)

【讨论】:

哦,我没想到这种关系,很好的发现。【参考方案3】:

我找到了以下 django 命令链,有没有更优雅的解决方案?

User.objects.filter(id__in=my_reply.comment.replies.values_list('user_id')) \
             .exclude(id=my_reply.user)

不过,这对我来说似乎是 2 个查询。

【讨论】:

这是一个子查询,而不是两个单独的查询。不过,可能有一种方法可以用 join 代替。

以上是关于如何访问反向关系django的反向关系的主要内容,如果未能解决你的问题,请参考以下文章

DjangoRestFramework - 如何使用模型序列化程序访问 OneToOneField 反向关系的其他字段?

如何在 django 模型中进行 2 层深度反向关系?

Django 啥是反向关系?

digao表关系有无名分组反向解析路由分发

Django 反向关系

Django:prefetch_related() 是不是遵循反向关系查找?