Django螺纹评论系统

时间:2014-07-21 07:48:10

标签: python django python-2.7 django-models django-views

(对不起我的英文)

我正在学习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)”命令,这给了我帖子及其子评论。但是当我想获得child命令的child命令时,一个新的查询正在运行。我可以将命令更改为...prefetch_related("child__child__child...")...,然后仍然为每个深层的子父关系运行一个新查询。有没有人有解决这个问题的想法?

1 个答案:

答案 0 :(得分: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)

这里的多对多需要a little extra work来创建关联,因为它使用了一个中间表。如果您想要一个纯one to many,那么您需要ForeignKey上的Comment,但是您只能使用prefetch_related而不是select_related,然后才会涉及PostitiveIntegerField额外的数据库命中。

这也更好,因为你没有无类型的外键引用(你的{{1}})。

然后,您需要将注释排列到树结构中,但这不在您的问题范围内。