我正在尝试序列化线程注释(最多 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