Django ORM:如何通过 join 或 select_related() 从 ForeignKey("self") 获取评论子项?

我正在尝试序列化线程注释(最多 3 lvl)并尽可能少地使用 sql 查询,但我被卡住了。

这里是我的模型

class Comment(models.Model):
    post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name="comments")
    name = models.CharField(max_length=50)
    email = models.EmailField()
    reply_to = models.ForeignKey("self",null=True,blank=True,on_delete=models.CASCADE)
    body = models.TextField()

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)


    def get_childs(self,obj_pk):
        return Comment.objects.filter(reply_to=obj_pk).select_related("reply_to")

和序列化器

class PostCommentSerializer(ModelSerializer):
    replies = SerializerMethodField()

    def get_replies(self,obj):
        return PostCommentSerializer(obj.get_childs(obj.pk),many=True).data

    class Meta:
        model = Comment
        fields = ("id","post","name","body","reply_to","replies")

class PostSerializer(ModelSerializer):
    replies = SerializerMethodField()

    def get_replies(self,obj):
        queryset = Comment.objects.filter(post_id=obj.id,reply_to=None)
        serializer = PostCommentSerializer(queryset,many=True)
        return serializer.data
    class Meta:
        model = Post
        fields = "__all__"

到目前为止,我设法通过递归查看了所有回复,但是通过这种方式,sql 查询的数量增长到了巨大的数字。如何通过一些 ORM 连接预加载所有评论(sql 数量不应取决于评论数量)并将其发送到序列化程序?

更新 1:提出了这个解决方案,我有疑问,这样做以减少 sql 数量是否正常?:

class PostCommentSerializer(ModelSerializer):
    replies = SerializerMethodField()

    def get_replies(self,obj):
        qs = Comment.objects.filter(reply_to=obj.pk).select_related("reply_to")
        qs2 = Comment.objects.exclude(reply_to=None).select_related("reply_to")

        replies_list = []
        for i in qs:
            replies_list.append({
                "id": i.id,"name": i.name,"body": i.body,"reply_to": i.reply_to.id,"replies" : []
            })

        for i in replies_list:
            for k in qs2:
                if k.reply_to:
                    if k.reply_to.id == i["id"]:
                        i["replies"].append(
                            {
                                "id": k.id,"name": k.name,"body": k.body,"reply_to": k.reply_to.id,}
                        )

        return replies_list
whfwt 回答:Django ORM:如何通过 join 或 select_related() 从 ForeignKey("self") 获取评论子项?

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/23551.html

大家都在问