基于Django contrib Comments 评论模块(详解)

基于Django contrib Comments 评论模块(详解),第1张

概述老版本的Django中自带一个评论框架。但是从1.6版本后,该框架独立出去了,也就是本文的评论插件。

老版本的Django中自带一个评论框架。但是从1.6版本后,该框架独立出去了,也就是本文的评论插件。

这个插件可给models附加评论,因此常被用于为博客文章、图片、书籍章节或其它任何东西添加评论。

一、快速入门

快速使用步骤:

安装包:pip install django-contrib-comments

在django的settings中的INSTALLED_APPS处添加'django.contrib.sites'进行app注册,并设置SITE_ID值。

在django的settings中的INSTALLED_APPS处添加'django_comments'.

运行manage.py migrate创建评论数据表。

在项目的根urls.py文件中添加URLs:url(r'^comments/',include('django_comments.urls')),

使用comment的模板标签,将评论嵌入到你的模板中。

1.1 comment模板标签

使用前请load标签:

{% load comments %}

1.1.1 评论对象

有两种办法:

1、直接引用评论对象。假设你的模板里已经有了一个叫做entry的评论对象,那么可以使用下面的方法获得该对象的评论次数:

{% get_comment_count for entry as comment_count %}

2、使用对象的类型和ID进行引用。比如,你知道一个blog的entry的ID为14,那么可以这么做:

{% get_comment_count for blog.entry 14 as comment_count %}

1.1.2 展示评论

使用render_comment_List或者get_comment_List 标签展示评论。

快速展示评论:

{% render_comment_List for [object] %}

这会使用插件里的comments/List.HTML模板来生成评论的HTML代码。

自定义展示评论:

{% get_comment_List for [object] as [varname] %}

实例:

{% get_comment_List for event as comment_List %}{% for comment in comment_List %}...{% endfor %}

这种方式下,你可以自己控制comment的展示方式,例如添加CSS,Js,结合bootstrap。

1.1.3 为评论添加超级链接

使用get_comment_permalink标签为评论添加永久的超级链接。用法:

{% get_comment_permalink comment_obj [format_string] %}

默认情况下,url中的命名锚以字母“c”加评论ID组成。例如: ‘c82'。当然,也可以通过下面的方式自定义:

{% get_comment_permalink comment "#c%(ID)s-by-%(user_name)s"%}

使用的是python标准格式化字符串的方式。

不管你是否自定义也好,你都必须在模板的合适位置提供一个匹配命名锚的机制。例如:

{% for comment in comment_List %}  <a name="c{{ comment.ID }}"></a>  <a href="{% get_comment_permalink comment %}">    permalink for comment #{{ forloop.counter }}  </a>  ...{% endfor %}

这块内容在使用safari浏览器的时候可能有个BUG。

1.1.4 评论数

获取评论数量:

{% get_comment_count for [object] as [varname] %}

例如:

{% get_comment_count for entry as comment_count %}
This entry has {{ comment_count }} comments.

1.1.5 评论表单

使用render_comment_form或者get_comment_form在页面上显示输入评论的表单。

快速显示表单:

{% render_comment_form for [object] %}

使用了默认的comments/form.HTML模板。简单说就是傻瓜式,最丑的界面。

自定义表单:

使用get_comment_form标签获取一个form对象,然后自己写逻辑控制它的展示方式。

{% get_comment_form for [object] as [varname] %}

展示例子(当然,这个也很丑!):

{% get_comment_form for event as form %}<table> <form action="{% comment_form_target %}" method="post">  {% csrf_token %}  {{ form }}  <tr>   <td colspan="2">    <input type="submit" name="submit" value="Post">    <input type="submit" name="prevIEw" value="PrevIEw">   </td>  </tr> </form></table>

提交地址:

上面的例子通过一个comment_form_target标签为form表单指定了正确的评论内容提交地址,请务必使用该方法:

<form action="{% comment_form_target %}" method="post">

提交后的重定向地址:

如果想在用户评论后将页面重定向到另外一个地址,请在form中插入一个隐藏的input标签,并命名为next,如下所示:

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

为已认证用户提供不同的表单:

很多时候我们要为登录的认证用户提供一些不同于匿名用户的内容,比如姓名、邮箱、网址等等,这些可以从用户数据和信息表内获得。其实,现在大多数的网站也只允许认证用户进行评论。要做到这点,你只需要简单的展示用户信息,或修改form表单即可,例如:

{% if user.is_authenticated %}  {% get_comment_form for object as form %}  <form action="{% comment_form_target %}" method="POST">  {% csrf_token %}  {{ form.comment }}  {{ form.honeypot }}  {{ form.content_type }}  {{ form.object_pk }}  {{ form.timestamp }}  {{ form.security_hash }}  <input type="hIDden" name="next" value="{% url 'object_detail_vIEw' object.ID %}" />  <input type="submit" value="提交评论" ID="ID_submit" />  </form>{% else %}  <p>请先<a href="{% url 'auth_login' %}">登录</a>后方可评论.</p>{% endif %}

上例中的honeypot(蜜罐,一种对攻击方进行欺骗的技术),能被用户看见,因此需要利用CSS将它隐藏起来。

#ID_honeypot {  display: none;}

如果你想同时接受匿名评论,只需要将上面的else从句后面的代码修改为一个标准的评论表单就可以了。

1.1.6 评论表单注意事项

该插件的评论表单有一些重要的反垃圾机制,你需要特别注意:

form中包含了一些隐藏的域,例如评论对象的时间戳、信息等,还有一个用于验证信息的安全哈希。如果有不怀好意的人篡改这些数据,评论会被拒绝。如果你使用自定义的form,请确保这些字段原样的被引用。

时间戳用于确保“回复攻击”不会持续太久时间。那些在请求表单和提交表单时间差过长的用户,将被拒绝提交评论。(注:官档的意思是评论提交有时间限制要求?)

评论表单有一个honeypot域。这是一个陷阱,如果该域被填入任何数据,那么该评论会被拒绝提交。因为垃圾发送者往往自动的为表单的所有域填入一定数据,视图制造一个合法合格的提交数据单。

默认表单中上面的域都通过CSS进行了隐藏,并提供警告。如果你是自定义表单,请确保进行了同样的工作!

最后,本插件的防御机制,依赖django的csrf中间件,请确保它是开着的!否则,请使用csrf_protect装饰器对所有的使用评论表单的vIEws进行装饰。

二、评论models

原型:class django_comments.models.Comment

它包含下面的字段:

content_object

评论的对象,例如一篇博客、图片、文章等等。这是一个GenericForeignKey外键。

content_type

一个指向ContentType的外键,用于保存评论对象的类型。要和上面的object区别开。

object_pk

对象的主键。一个TextFIEld域。

site

评论提交的站点。外键。

user

指向评论的用户的外键。当匿名时,值为空。

user_name

用户名

user_email

用户邮箱

user_url

用户的网址。(很久以前的形式,现在基本都不要求填这个了。)

comment

评论的内容主体

submit_date

提交日期

ip_address

用户ip

is_public

True,则显示到页面上。

False,不显示到页面上。

is_removed

True,如果评论被移除了。用于跟踪那些被移除的评论,而不是简单的把他们直接删除。

(例如,有人言论不合适,管理员可以移除它,但是在原位置留下提示信息。)

源码:

from __future__ import unicode_literalsfrom django.conf import settingsfrom django.contrib.ContentTypes.fIElds import GenericForeignKeyfrom django.contrib.ContentTypes.models import ContentTypefrom django.contrib.sites.models import Sitefrom django.db import modelsfrom django.utils import timezonefrom django.utils.enCoding import python_2_unicode_compatiblefrom django.utils.translation import ugettext_lazy as _try:  from django.urls import reverseexcept importError:  from django.core.urlresolvers import reverse # Django < 1.10from .managers import CommentManagerCOMMENT_MAX_LENGTH = getattr(settings,'COMMENT_MAX_LENGTH',3000)class BaseCommentAbstractModel(models.Model):  """  An abstract base class that any custom comment models probably should  subclass.  """  # Content-object fIEld  content_type = models.ForeignKey(ContentType,verbose_name=_('content type'),related_name="content_type_set_for_%(class)s",on_delete=models.CASCADE)  object_pk = models.TextFIEld(_('object ID'))  content_object = GenericForeignKey(ct_fIEld="content_type",fk_fIEld="object_pk")  # Metadata about the comment  site = models.ForeignKey(Site,on_delete=models.CASCADE)  class Meta:    abstract = True  def get_content_object_url(self):    """    Get a URL suitable for redirecting to the content object.    """    return reverse(      "comments-url-redirect",args=(self.content_type_ID,self.object_pk)    )@python_2_unicode_compatibleclass CommentAbstractModel(BaseCommentAbstractModel):  """  A user comment about some object.  """  # Who posted this comment? If ``user`` is set then it was an authenticated  # user; otherwise at least user_name should have been set and the comment  # was posted by a non-authenticated user.  user = models.ForeignKey(settings.AUTH_USER_MODEL,verbose_name=_('user'),blank=True,null=True,related_name="%(class)s_comments",on_delete=models.SET_NulL)  user_name = models.CharFIEld(_("user's name"),max_length=50,blank=True)  # Explicit `max_length` to apply both to Django 1.7 and 1.8+.  user_email = models.EmailFIEld(_("user's email address"),max_length=254,blank=True)  user_url = models.URLFIEld(_("user's URL"),blank=True)  comment = models.TextFIEld(_('comment'),max_length=COMMENT_MAX_LENGTH)  # Metadata about the comment  submit_date = models.DateTimeFIEld(_('date/time submitted'),default=None,db_index=True)  ip_address = models.GenericIPAddressFIEld(_('IP address'),unpack_ipv4=True,null=True)  is_public = models.BooleanFIEld(_('is public'),default=True,help_text=_('Uncheck this Box to make the comment effectively '                        'disappear from the site.'))  is_removed = models.BooleanFIEld(_('is removed'),default=False,help_text=_('Check this Box if the comment is inappropriate. '                         'A "This comment has been removed" message will '                         'be displayed instead.'))  # Manager  objects = CommentManager()  class Meta:    abstract = True    ordering = ('submit_date',)    permissions = [("can_moderate","Can moderate comments")]    verbose_name = _('comment')    verbose_name_plural = _('comments')  def __str__(self):    return "%s: %s..." % (self.name,self.comment[:50])  def save(self,*args,**kwargs):    if self.submit_date is None:      self.submit_date = timezone.Now()    super(CommentAbstractModel,self).save(*args,**kwargs)# 后面省略

三、自定义评论框架

很明显,这个插件还不够强大,功能还不够丰富,界面还不够美观。我们必须自定义整体框架!那么怎么办呢?

假如你自己在django-contrib-commests的基础上二次开发了一个叫做my_comment_app的评论框架。请这么设置它:

INSTALLED_APPS = [  ...  'my_comment_app',...]COMMENTS_APP = 'my_comment_app'

在my_comment_app的__init__.py中定义新的模型级别的动作或行为。

简单的例子

例如有的网站希望用户在评论的时候,提供一个标题Title。很显然现有的插件中的model没有这个字段,你必须自定义。怎么做?分三步:

1.创建一个自定义的comment模型,添加一个Title字段;

2.创建一个自定义的comment form模型,同样地增加Title字段;

3.自定义一个comment_app,定义一些新的方法,然后通知Django

如下创建包:

my_comment_app/  __init__.py  models.py  forms.py

在models.py文件中编写一个CommentWithTitle模型类:

from django.db import modelsfrom django_comments.abstracts import CommentAbstractModelclass CommentWithTitle(CommentAbstractModel):  Title = models.CharFIEld(max_length=300)

然后在forms.py文件中编写新的form类,同时重写CommentForm.get_comment_create_data()方法,帮助我们增加Title字段。

from django import formsfrom django_comments.forms import CommentFormfrom my_comment_app.models import CommentWithTitleclass CommentFormWithTitle(CommentForm):  Title = forms.CharFIEld(max_length=300)  def get_comment_create_data(self):    # 使用父类的数据的同时增加Title字段    data = super(CommentFormWithTitle,self).get_comment_create_data()    data['Title'] = self.cleaned_data['Title']    return data

注:在django_comments.forms中提供了一些“helper”类,帮助我们更方便地进行自定义。

最后在my_comment_app/init.py中编写方法,通知Django我们所做的改动:

def get_model():  from my_comment_app.models import CommentWithTitle  return CommentWithTitledef get_form():  from my_comment_app.forms import CommentFormWithTitle  return CommentFormWithTitle

注意:上面的import语句必须放在函数体内部,因为最新版本的django不允许在app的__init__.py的顶部import模块

注意:不要循环导入模块,不要重复引入模块!

更多的自定义API

上面的例子是个通用的做法,如果还不能满足需求,那么可以使用下面的API,所有的自定义app都必须定义至少其中之一:

django_comments.get_model()

返回你要使用的自定义comment类。(请结合上面的例子进行理解。)

django_comments.get_form()

返回你要使用的自定义的comment form类。同上。

django_comments.get_form_target()

返回form在post时,提交的URL地址。

django_comments.get_flag_url()

返回“flag this comment”视图的URL

默认情况下,它指的是django_comments.vIEws.moderation.flag()

django_comments.get_delete_url()

返回“delete this comment” 视图的URL

默认情况下是django_comments.vIEws.moderation.delete()

django_comments.get_approve_url()

返回“approve this comment from moderation” 视图的URL

默认情况下是django_comments.vIEws.moderation.approve()

总结: Django Comment 评论插件原生的界面比较丑陋,但是通过自定制,可以改写出美观、适用的评论系统,比如博主个人主页的评论系统!

以上这篇基于Django contrib Comments 评论模块(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的基于Django contrib Comments 评论模块(详解)全部内容,希望文章能够帮你解决基于Django contrib Comments 评论模块(详解)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1201096.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存