Django撸博客之添加通用评论功能

需求简述

  • 需要给文章添加可评论的功能
  • 评论可回复(评论一个评论)

简单分析

  • 评论最起码需要评论两种类型: 文章(Post)和评论(Comment), 显然外键得有两个
  • 如果引入两个外键会有以下问题:
    • 过度冗余
    • 扩展性差(如果又要给新的教程(Tutorial)类型添加评论,又加一个外键吗?)
  • 我们需要的是,不管评论的对象是什么东西, 我们的评论都可以适用.

解决方案

  • 其实我们需要的一个通用外键, 这个外键可以代表任何类型的对象, 这就是django内置的 ContenttypeGenericRelation, 即通用类型和通用关系.

详细说明

  • 我们要评论的对象即确定又不确定, 即需要确定唯一的一个对象, 但又不能确定是哪个唯一的对象. 只要能正确的锁定这个唯一的对象, 那么我们的评论就可以作用于这个对象
  • 在数据库中, 唯一确定一个对象,需要提供两个条件: 表名(Table,django中的模型名)和主键(PK), 有了这两个条件, 就能唯一确定一个对象
  • django中有一张表保存了所有的模型名字, 并且映射成了模型,并提供接口供使用. Contenttype

因此, 在我们的评论模型(Comment)中,只需要这样写:

from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import \
    GenericForeignKey, GenericRelation


class Comment(models.Model):
    author = models.ForeignKey(User,
                               verbose_name=u'评论者',
                               related_name='comments')
    created = models.DateTimeField(u'时间', auto_now=True)
    content = models.TextField(u'评论内容')
    likes = models.IntegerField(u'顶', default=0)
    user_likes = models.ManyToManyField(User,
                                        verbose_name=u'点赞的人',
                                        related_name='comments_liked')
    # 自己对自己的评论, 也就是评论的回复
    comments = GenericRelation('Comment')  

    # 外键为通用类型, 什么类型都有可能
    content_type = models.ForeignKey(ContentType)

    # 类型的id
    object_id = models.PositiveIntegerField()

    # 类型和id共同唯一确定一个对象
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self, ):
        return '%s对%s的评论' % (self.author.username, self.content_object)

在博客文章(Post)中这样写:

from django.db import models
from django.contrib.contenttypes.fields import GenericRelation

class Post(models.Model):
    comments = GenericRelation(Comment)

这样, 不管什么地方需要评论,只需要使用GenericRelation来添加评论就行了.

获取评论:

    p = Post.objects.all()[0]
    comments = p.comments.all()

猜你喜欢

转载自blog.csdn.net/DrCBin/article/details/80213561
今日推荐