起步

本篇使用的是官方提供的组件 django_comments 进行。由于文档上对快速使用的介绍顺序不是很友好,所以这里进行调整讲述,如果将使用评论框架。

安装

评论组件原本是Django内置的,而后从1.6就分离出去作为独立的组件了,因此需要自己安装。

pip install django-contrib-comments

在配置 settings.py 中加入:

INSTALLED_APPS = [
    ...
    'django.contrib.sites',
    'django_comments',
]
SITE_ID = 1

评论组件需要用到 django.contrib.sites ,然后执行 python manage.py migrate 同步数据库结构。

urls.py 中加入路由规则:

urlpatterns = [
    ...
    url(r'^comments/', include('django_comments.urls')),
    ...
]

使用

评论组件能对 Django 任何模型实例关联评论的。此处假设有个实体是文章模型的实例:entry = models.Article.objects.get(id=1)

添加评论

组件提供了一个默认的评论表单,在使用标签之前导入评论库模块的模版标签:

{% load comments %}

使用组件提供的 get_comment_list 标签为实体创建一个表单:

{% render_comment_form for entry %}

这是默认的表单,模板采用了 comments/form.html 文件,渲染出来的效果如下:

20200104235733.png

填写表单后提交就能成功提交了,评论成功后会调整到一个简陋的成功页面。

如果对默认生成的表单不满意,可以通过 as 取个别名。表单就不会自动渲染,从而可以进行手动设置:

{% get_comment_form for entry as form %}
<form action="{% comment_form_target %}" method="post">
    {% csrf_token %}
    {# 必须的字段 #}
    {{ form.object_pk }}
    {{ form.content_type }}
    {{ form.timestamp }}
    {{ form.site }}
    {{ form.submit_date }}
    {{ form.security_hash }}
    <p><label for="id_name">名字: </label>{{ form.name }}</p>
    <p><label for="id_email">邮箱: </label>{{ form.email }}</p>
    <p><label for="id_url">站点: </label>{{ form.url }}</p>
    <p><label for="id_comment">内容: </label>{{ form.comment }}</p>
    <span style="display: none;">{{ form.honeypot }}</span>

    <input type="submit" value="提交" />
</form>

就能得到自定义的展示方式:

20200105004936.png

表单中字段及其含义如下:

  • name: 姓名;
  • email:邮箱;
  • url:网址;
  • comment:内容;
  • honeypot:防止机器人评论,一般设置为隐藏;
  • comment_type:评论对象的表,与后台有关;
  • object_pk:对应的文章id;
  • timestamp: 时间戳;
  • security_hash:安全检测。

设置评论后跳转的页面

要指定评论后重定向的URL,可以在表单中添加 next 字段:

<input type="hidden" name="next" value="{% url 'my_comment_was_posted' %}" />

获取实体的评论数量

{% get_comment_count for entry as comment_count %}
<p>评论数:{{ comment_count }}:</p>

评论的展示

使用默认的展示效果:

{% render_comment_list for entry %}

渲染:

20200105005726.png

设置自定义显示:

{% get_comment_list for entry as comment_list %}
{% for comment in comment_list %}
  <p>评论人: {{ comment.user_name }} 发表于 {{ comment.submit_date }}</p>
  <p>内容:{{ comment.comment }}</p>
{% endfor %}

自定义显示的渲染:

20200105011826.png

评论链接

与其说是评论链接,不如说是链接+锚点。它是能指向到实体页的目标评论上。

# urls.py
re_path(r'^article/(?P<id>\d+)/$', views.article_detail, name="article_detail"),

# models.py
class Article:
    @models.permalink
    def get_absolute_url(self):
       return ('article_detail', (), {'id': self.id})

# template
{% get_comment_list for entry as comment_list %}
{% for comment in comment_list %}
  <p>评论人: {{ comment.user_name }} 发表于 {{ comment.submit_date }}</p>
    <p><a name="c{{ comment.id }}" id="c{{ comment.id }}">锚点</a></p>
  <p>内容:{{ comment.comment }}</p><a href="{% get_comment_permalink comment "#c%(id)s" %}">
      link #{{ forloop.counter }}
  </a>
{% endfor %}

定制评论框架

如果评论模型不太符合需求,那么也可以对模型进行定制。大多数情况下,我都是推荐进行定制化的,哪怕开始时只是简单的继承,但很难保证甲方不会脑热。

评论框架也提供了可定制性的接口,那么需要定义的有模型,表单。

# models.py
from django_comments.abstracts import CommentAbstractModel

class CommentWithTitle(CommentAbstractModel):
    title = models.CharField(max_length=300)

# forms.py
from django_comments.forms import CommentForm
from app.models import CommentWithTitle

class CommentFormWithTitle(CommentForm):
    title = forms.CharField(max_length=300)

class CommentFormWithTitle(CommentForm):
    title = forms.CharField(max_length=300)

    def get_comment_create_data(self, site_id=None):
        # Use the data of the superclass, and add in the title field
        data = super(CommentFormWithTitle, self).get_comment_create_data(site_id)
        data['title'] = self.cleaned_data['title']
        return data

拓展了评论模型和表单后,要通知评论框架使用我们新写的模型,还需要在 app 的 __init__.py 中定义两个函数:

# <app_name>/__init__.py
def get_model():
    from app.models import CommentWithTitle # 防止循环导入,因此写在函数内部
    return CommentWithTitle

def get_form():
    from app.forms import CommentFormWithTitle
    return CommentFormWithTitle

settings.py 载入该 app 和设置 COMMENT_APP 项:

# settings.py
INSTALLED_APPS = [
    ...
    'app',  # 包含自定义评论模型的 app 名
    ...
]

COMMENTS_APP = 'app'  # 指定框架使用哪个 app

评论的管理

评论功能往往还设计了审核的功能,以及可以设置实体不允许被评论。 django_comments.moderation 提供了一个通用的可以拓展的评论审核系统。

禁用评论

对实体模型添加一个 enable_comments 字段还表示它能否被评论

from django.db import models

class Entry(models.Model):
    title = models.CharField(maxlength=250)
    body = models.TextField()
    pub_date = models.DateField()
    enable_comments = models.BooleanField()

from django_comments.moderation import CommentModerator, moderator

class EntryModerator(CommentModerator):   # 控制能否评论的类
    email_notification = False
    enable_field = 'enable_comments'

moderator.register(User, EntryModerator)  # 注册到评论框架中去

如果 enable_commentsFalse ,那么该实体禁止评论;若为 True 则允许评论。我们还可以在成功评论后,做发送电子邮件之类的事情。

评论审核

可以通过重写父类的 moderate 来起到不公开评论的功能:

class EntryModerator(CommentModerator):
    ...
    def moderate(self, comment, content_object, request):
        return True

返回 True 表示评论需要审核,这种情况下,评论实例的 is_public 字段会被设为 False 。若返回 Falseis_public 字段不做修改。

评论后通知

如果需要在评论保存后进行通知,那么可以通过重写 pre_save_moderation 等实现:

class EntryModerator(CommentModerator):
    ...
    def pre_save_moderation(sender, comment, request, **kwargs):
        super().pre_save_moderation(sender, comment, request, **kwargs)
        # code...

    def post_save_moderation(sender, comment, request, **kwargs):
        super().post_save_moderation(sender, comment, request, **kwargs)
        # code...

总结

本文其实只是对官方文档进行整理,方便我们接入评论框架,更多需要的请阅读官方文档:https://django-contrib-comments.readthedocs.io/en/latest/index.html


本文由 hongweipeng 创作,采用 署名-非商业性使用-相同方式共享 3.0,可自由转载、引用,但需署名作者且注明文章出处。

如果对您有用,您的支持将鼓励我继续创作!