Django 多线程评论系统
(抱歉我的英语不好)
我正在学习Python和Django。现在,我的挑战是开发一个可以进行多层评论的通用评论系统。这里有两个模型,分别是帖子(Post)和评论(Comment)。
- 帖子可以被评论。
- 评论也可以被评论。(可以无限层级)
- 系统中不应该出现n+1查询的问题。(无论评论有多少,都不应该增加查询的次数)
我现在的模型是这样的:
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
child = generic.GenericRelation(
'Comment',
content_type_field='parent_content_type',
object_id_field='parent_object_id'
)
class Comment(models.Model):
content = models.TextField()
child = generic.GenericRelation(
'self',
content_type_field='parent_content_type',
object_id_field='parent_object_id'
)
parent_content_type = models.ForeignKey(ContentType)
parent_object_id = models.PositiveIntegerField()
parent = generic.GenericForeignKey(
"parent_content_type", "parent_object_id")
我的模型设计得对吗?我该如何获取某个帖子的所有评论(包括层级关系),而不出现n+1查询的问题呢?
注意:我知道mttp和其他模块,但我想学习这个系统。
编辑:我运行了“Post.objects.all().prefetch_related("child").get(pk=1)
”这个命令,这样我得到了帖子和它的子评论。但是当我想获取子评论的子评论时,又会运行一个新的查询。我可以把命令改成...prefetch_related("child__child__child...")...
,但这样每一层的父子关系都会运行新的查询。有没有人知道怎么解决这个问题?
1 个回答
2
如果你想通过一次查询获取某个帖子下的所有评论,那么最好让每条评论都链接到相关的帖子。同时,你可以用一个单独的链接来表示父评论。
简单来说:
class Post(models.Model):
...
comments = models.ManyToManyField('Comment')
# link to all comments, even children of comments
class Comment(models.Model):
...
child_comments = models.ManyToManyField('Comment')
# You may find it easier to organise these into a tree
# if you use a parent_comment ForeignKey. That way the
# top level comments have no parent and can be easily spotted.
Post.objects.all().select_related('comments').get(pk=1)
在这种情况下,很多对很多的关系需要多花一点功夫来建立关联,因为它需要一个中间表。如果你想要一个纯粹的一对多关系,那么你需要在Comment
上使用一个ForeignKey
,但这样你就只能使用prefetch_related
,而不能使用select_related
,这会导致多一次数据库查询。
这样做的好处是,你不会有一个没有类型的外键引用(你的PostitiveIntegerField
)。
接下来,你需要把评论整理成树状结构,但这超出了你问题的范围。