简体   繁体   中英

Django Threaded Commenting System

(and sorry for my english)

I am learning Python and Django. Now, my challange is developing threaded generic comment system. There is two models, Post and Comment.

-Post can be commented.

-Comment can be commented. (endless/threaded)

-Should not be a n+1 query problem in system. (No matter how many comments, should not increase the number of queries)

My current models are like this:

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")

Are my models right? And how can i get all comment (with hierarchy) of post, without n+1 query problem?

Note: I know mttp and other modules but I want to learn this system.


Edit: I run " Post.objects.all().prefetch_related("child").get(pk=1) " command and this gave me post and its child comment. But when I wanna get child command of child command a new query is running. I can change command to ...prefetch_related("child__child__child...")... then still a new query running for every depth of child-parent relationship. Is there anyone who has idea about resolve this problem?

If you want to get all comments on a post with a single query then it would be good to have every comment link to the asssociated post. You can use a separate link to indicate the parent comment.

Basically:

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)

The many to many in this takes a little extra work to create the association, as it uses an intermediate table. If you want a pure one to many then you need a ForeignKey on the Comment but then you are restricted to a prefetch_related instead of a select_related , which then involves an extra database hit.

This is also better in that you do not have an untyped foreign key reference (your PostitiveIntegerField ).

You then need to arrange the comments into a tree structure, but that is outside the scope of your question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM