【问题标题】:Django Threaded Commenting SystemDjango 线程评论系统
【发布时间】:2014-09-11 15:49:57
【问题描述】:

(对不起我的英语)

我正在学习 Python 和 Django。现在,我的挑战是开发线程化的通用评论系统。有两种模型,Post 和 Comment。

-帖子可以评论。

-Comment 可以被评论。 (无尽/线程)

-不应该是系统中的 n+1 查询问题。 (无论多少cmets,都不应该增加查询次数)

我现在的模型是这样的:

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...")...,然后仍然为每个子父关系深度运行一个新查询。有没有人有解决这个问题的想法?

【问题讨论】:

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


    【解决方案1】:

    如果您想通过单个查询获取帖子中的所有 cmets,那么最好将每个评论链接都指向相关帖子。您可以使用单独的链接来指示父评论。

    基本上:

    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,那么你需要在Comment 上使用ForeignKey,但是你只能使用prefetch_related 而不是select_related,这会涉及额外的数据库命中。

    这也更好,因为您没有无类型的外键引用(您的PostitiveIntegerField)。

    然后您需要将 cmets 排列成树结构,但这超出了您的问题范围。

    【讨论】:

      猜你喜欢
      • 2018-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-07
      相关资源
      最近更新 更多