Django+Bootstrap+Mysql 搭建个人博客(六)
6.1.comments插件
(1)安装
pip install django-contrib-comments
(02)settings
INSTALLED_APPS = [
'django.contrib.sites',
'django_comments',
]
SITE_ID =1

(3)website/url
url(r'^comments/', include('django_comments.urls')),
(4)修改源码
django_comments/abstracts.py第36行
原代码
site = models.ForeignKey(Site, on_delete=models.CASCADE)
修改后
site = models.ForeignKey(Site,default=None,blank=True,null=True,on_delete=models.CASCADE)
(5)修改源码
django_comments/abstracts.py第52行
修改和增加了几个字段
class 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)
# 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,null=True,default='xxx@xxx.com')
user_url = models.URLField(_("user's URL"), blank=True,null=True,default='https://xxx.xxx.xxx.xxx')
user_name = models.CharField(_("user's name"), max_length=50, blank=True)
user_img = models.ImageField(upload_to="user_images", blank=True,null=True,verbose_name="用户图像")
comment_title = models.CharField(max_length=256,default="无标题", blank=True,null=True,verbose_name="评论标题")
parent_comment = models.ForeignKey('self',default=None, blank=True,null=True,related_name="child_comment",on_delete=models.CASCADE) level = models.PositiveIntegerField(default=0, blank=True,null=True,verbose_name='评论层级') comment = models.TextField(_('comment'), max_length=COMMENT_MAX_LENGTH) . . . .
(6)修改源码
django_comments/admin.py第29和37行
_('Content'),
{'fields': ('user', 'user_name', 'user_email', 'user_url', 'comment','comment_title','parent_comment')}
list_display = ('comment_title','name', 'content_type', 'object_pk', 'ip_address', 'submit_date', 'is_public', 'is_removed')
(7)修改源码
django_comments/forms.py第97行表单
class CommentDetailsForm(CommentSecurityForm): """ Handles the specific details of the comment (name, comment, etc.).
"""
# name = forms.CharField(label=pgettext_lazy("Person name", "Name"), max_length=50)
# email = forms.EmailField(label=_("Email address"))
# url = forms.URLField(label=_("URL"), required=False)
# Translators: 'Comment' is a noun here.
comment = forms.CharField(label=_('Comment'), widget=forms.Textarea,
max_length=COMMENT_MAX_LENGTH)
comment_title = forms.CharField(max_length=256,label=_('标题'))
parent_id = forms.IntegerField(min_value=-1,label=_('父评论的id'))
level = forms.IntegerField(min_value=0,label=_('层级'),) . . .
def get_comment_create_data(self, site_id=None):
"""
Returns the dict of data to be used to create a comment. Subclasses in
custom comment apps that override get_comment_model can override this
method to add extra fields onto a custom comment model.
"""
parent_id = self.cleaned_data['parent_id']
if parent_id <= 0:
parent = None
_level = self.cleaned_data['level']
else:
parent = get_model().objects.get(id=parent_id)
_level = self.cleaned_data['level'] + 4 # 4是缩进
return dict(
content_type=ContentType.objects.get_for_model(self.target_object),
object_pk=force_text(self.target_object._get_pk_val()),
# user_name=self.cleaned_data["name"],
# user_email=self.cleaned_data["email"],
# user_url=self.cleaned_data["url"],
comment_title = self.cleaned_data['comment_title'],
parent_comment = parent,
level = _level,
comment=self.cleaned_data["comment"],
submit_date=timezone.now(),
site_id=site_id or getattr(settings, "SITE_ID", None),
is_public=True,
is_removed=False,
)
(8)修改源码
django_comments/views/comments.py第97行表单
52行
# 添加
if not request.session.get('login', None) and not user_is_authenticated:
return redirect("/")
116行
# if user_is_authenticated:
# comment.user = request.user
#添加
if request.session.get('login',None):
comment.user_name = request.session['screen_name']
comment.user_img = request.session['profile_image_url']
以上都修改完后
python manage.py makemigtations python manage.py migrate
6.2.评论表单
detail.html
<div class="row">
<hr />
{% get_comment_form for entry as form %}
{% get_comment_count for entry as comment_count %}
<h3 >评论总数: {{ comment_count }}</h3>
<hr />
</div>
<div class="row">
<form class="form-horizontal" action="{% comment_form_target %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="input_title" class="pull-left control-label">评论标题:</label>
<div class="col-sm-6">
<input class="form-control" name="comment_title" id="input_title" placeholder="请输入标题" required />
</div>
</div>
<div class="form-group">
<label for="input_comment" class="pull-left control-label">评论内容:</label>
<div class="col-sm-6">
<textarea style="resize:none;" class="form-control" rows=6 name="comment" id="input_comment" placeholder="在此输入评论" required></textarea>
</div>
</div>
<span style="display: none;">{{ form.honeypot }}</span>
{{ form.content_type }}
{{ form.object_pk }}
{{ form.timestamp }}
{{ form.security_hash }}
<input type="hidden" name="next" value="{% url 'blog:blog_detail' entry.id %}" />
<input name="parent_id" type="hidden" value="-1" />
<input name=" />
<div class="form-group col-sm-7">
<div class="pull-left" style="margin-left: 68px;">
<button type="reset" class="btn btn-default"><span class="glyphicon glyphicon-repeat"></span> 重置</button>
</div>
<div class="pull-right" style="margin-right: 12px;">
<button type="submit" class="btn btn-success" id="id_submit"><span class="glyphicon glyphicon-send"></span> 评论</button>
</div>
</div>
</form>
</div>
效果:

现在测试评论,可以添加成功,但是还不能显示
6.3.显示评论
(1)views.py
from django_comments.models import Comment
def detail(request,blog_id):
# entry = models.Entry.objects.get(id=blog_id)
entry = get_object_or_404(models.Entry,id=blog_id)
md = markdown.Markdown(extensions=[
'markdown.extensions.extra',
'markdown.extensions.codehilite',
'markdown.extensions.toc',
])
entry.body = md.convert(entry.body)
entry.toc = md.toc
entry.increase_visiting()
comment_list = list()
def get_comment_list(comments):
for comment in comments:
comment_list.append(comment)
children = comment.child_comment.all()
if len(children) > 0:
get_comment_list(children)
top_comments = Comment.objects.filter(object_pk=blog_id, parent_comment=None,
content_type__app_label='blog').order_by('-submit_date')
get_comment_list(top_comments)
return render(request, 'blog/detail.html', locals())
(2)detail.html
<div class="row">
<hr />
{% get_comment_form for entry as form %}
{% get_comment_count for entry as comment_count %}
<h3 >评论总数: {{ comment_count }}</h3>
<hr />
</div>
{# 评论表单#}
{% if request.session.login or request.user.is_authenticated %}
<div class="row">
<form class="form-horizontal" action="{% comment_form_target %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="input_title" class="pull-left control-label">评论标题:</label>
<div class="col-sm-6">
<input class="form-control" name="comment_title" id="input_title" placeholder="请输入标题" required />
</div>
</div>
<div class="form-group">
<label for="input_comment" class="pull-left control-label">评论内容:</label>
<div class="col-sm-6">
<textarea style="resize:none;" class="form-control" rows=6 name="comment" id="input_comment" placeholder="在此输入评论" required></textarea>
</div>
</div>
<span style="display: none;">{{ form.honeypot }}</span>
{{ form.content_type }}
{{ form.object_pk }}
{{ form.timestamp }}
{{ form.security_hash }}
<input type="hidden" name="next" value="{% url 'blog:blog_detail' entry.id %}" />
<input name="parent_id" type="hidden" value="-1" />
<input name="level" type="hidden" value="0" />
<div class="form-group col-sm-7">
<div class="pull-left" style="margin-left: 68px;">
<button type="reset" class="btn btn-default"><span class="glyphicon glyphicon-repeat"></span> 重置</button>
</div>
<div class="pull-right" style="margin-right: 12px;">
<button type="submit" class="btn btn-success" id="id_submit"><span class="glyphicon glyphicon-send"></span> 评论</button>
</div>
</div>
</form>
</div>
{% else %}
<h3>登陆后才可以评论</h3>
{% endif %}
<hr />
{# 评论显示区#}
<div class="row">
{% for comment in comment_list %}
<div class="single_comment" style="margin-left: {{ comment.level }}em">
<div>
{% if comment.user_img %}
<img src="{{ comment.user_img }}" alt="user_image" />
{% else %}
<img src="{% static 'blog/images/cl.jpg' %}" />
{% endif %}
</div>
<div class="col-md-11 comment-content" style="margin-bottom: 10px;">
<strong>{{ comment.comment_title }}</strong>
<div>
{% if comment.parent_comment %}
{{ comment.user_name }}{{ request.user }}
<i class="glyphicon glyphicon-share-alt"></i>
{{ comment.parent_comment.user_name }}{{ request.user }}
{% else %}
By
{{ comment.user_name }}{{ request.user }}
On
{% endif %}
<em>{{ comment.submit_date }}</em>
{% if request.session.login or request.user.is_authenticated %}
<a href="#">回复</a>
{% endif %}
</div>
<br />
<p>{{ comment.comment }}</p>
</div>
</div>
{% endfor %}
</div>
</div>
(3)static/blog/images/cl.jpg
设置默认图片(如果没有登录就显示默认图片,为了测试评论)

(4)blog/blog_comment.css
hr {
border-top: 1px solid lightgrey;
border-bottom: 1px solid #fff;
}
.single_comment {
margin-bottom: 20px;
font-family: "Microsoft Yahei","微软雅黑",Arial,Helvetica,STHeiti,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
}
.single_comment img {
width:50px;
height:50px;
border-radius:50%;
overflow:hidden;
float: left;
margin-left: 10px;
margin-top: 5px;
}
.single_comment p {
margin-bottom:;
}
.comment-content {
border-bottom: 1px dashed lightgrey;
border-left: 1px dashed #2d7da4;
padding-bottom: 5px;
}
detail.html引用
{% block css %}
<link rel="stylesheet" href="{% static 'blog/css/github.css' %}">
<link rel="stylesheet" href="{% static 'blog/css/blog_comment.css' %}">
{% endblock %}
效果:

6.4.评论回复
(1)blog/urls.py
url(r'^reply/(?P<comment_id>\d+)/$', views.reply, name='comment_reply'),
(2)views.py
from django_comments import models as comment_models
def reply(request, comment_id):
if not request.session.get('login', None) and not request.user.is_authenticated():
return redirect('/')
parent_comment = get_object_or_404(comment_models.Comment, id=comment_id)
return render(request, 'blog/reply.html', locals())
(3)blog/reply.html
{% extends 'blog/base.html' %}
{% load comments %}
{% load static %}
{% block title %}回复评论{% endblock %}
{% block css %}
<link rel="stylesheet" href="{% static 'blog/css/blog_comment.css' %}">
{% endblock %}
{% block content %}
<div class="container-fluid" style="margin: 30px 50px 0 50px;min-height: 450px;">
<div class="row">
<div class="single_comment">
<div>
{% if request.session.login %}
<img src="{{ parent_comment.user_img }}" alt="user_img" />
{% else %}
<img src="{% static 'blog/images/cl.jpg' %}" alt="admin_img" />
{% endif %}
</div>
<div class="col-md-11">
<strong>{{ parent_comment.comment_title }}</strong>
<div class="small">
<strong>{{ parent_comment.username }} {{ request.user }}</strong>
<em>{{ parent_comment.submit_date }}</em>
</div>
<br />
<p>{{ parent_comment.comment }}</p>
</div>
</div>
</div>
<br />
{% if request.session.login or request.user.is_authenticated %}
<div class="row" style="margin-left: 30px;">
<h3>回复 {{ parent_comment.username }}{{ request.user }} 的评论:</h3>
{% get_comment_form for parent_comment.content_object as form %}
<form class="form-horizontal" action="{% comment_form_target %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="input_title" class="pull-left control-label">评论标题:</label>
<div class="col-sm-6">
<input class="form-control" name="comment_title" id="input_title" placeholder="请输入标题" required />
</div>
</div>
<div class="form-group">
<label for="input_comment" class="pull-left control-label">评论内容:</label>
<div class="col-sm-6">
<textarea style="resize:none;" class="form-control" rows=6 name="comment" id="input_comment" placeholder="在此输入评论" required></textarea>
</div>
</div>
<span style="display: none;">{{ form.honeypot }}</span>
{{ form.content_type }}
{{ form.object_pk }}
{{ form.timestamp }}
{{ form.security_hash }}
<input type="hidden" name="next" value="{% url 'blog:blog_detail' parent_comment.content_object.id %}" />
<input name="parent_id" type="hidden" value="{{ parent_comment.id }}" />
<input name="level" type="hidden" value="{{ parent_comment.level }}" />
<div class="form-group col-sm-7">
<div class="pull-left" style="margin-left: 68px;">
<button type="reset" class="btn btn-default"><span class="glyphicon glyphicon-repeat"></span> 重置</button>
</div>
<div class="pull-right" style="margin-right: 12px;">
<button type="submit" class="btn btn-success" id="id_submit"><span class="glyphicon glyphicon-send"></span> 评论</button>
</div>
</div>
</form>
</div>
{% else %}
<h3>登陆后才可以评论</h3>
{% endif %}
<br />
<div>
<a href="{% url 'blog:blog_detail' parent_comment.content_object.id %}">暂时不评论,返回先前页面!</a>
</div>
</div>
{% endblock %}
(4)detail.html
<a href="{% url 'blog:comment_reply' comment.id %}">回复</a>
测试回复功能如下:

Django+Bootstrap+Mysql 搭建个人博客(六)的更多相关文章
- Django+Bootstrap+Mysql 搭建个人博客(一)
1.1.环境搭建 (1)虚拟环境 mkvirtualenv website pip install django==1.11.7 (2)创建项目和app:website和blog (3)设置中文set ...
- Django+Bootstrap+Mysql 搭建个人博客(五)
5.1.自定义403,404和500页面 (1)website/urls.py from blog import views as blog_views handler403 = blog_views ...
- Django+Bootstrap+Mysql 搭建个人博客(四)
4.1.博客分类 (1)blog_tags.py @register.simple_tag def get_categories(): return Category.objects.all() @r ...
- Django+Bootstrap+Mysql 搭建个人博客(三)
3.1.分页功能 (1)views.py from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger def make ...
- Django+Bootstrap+Mysql 搭建个人博客(二)
2.1.博客首页设计 (1)settings.py MEDIA_ROOT = os.path.join(BASE_DIR,'media').replace("//","/ ...
- Django+Bootstrap+Mysql 搭建个人博客 (六)
6.1.comments插件 (1)安装 pip install django-contrib-comments (02)settings INSTALLED_APPS = [ 'django.con ...
- Python Web开发:Django+BootStrap实现简单的博客项目
创建blog的项目结构 关于如何创建一个Django项目,请查看[Python Web开发:使用Django框架创建HolleWorld项目] 创建blog的数据模型 创建一个文章类 所有开发都是数据 ...
- django入门--django-blog-zinnia搭建个人博客
1.安装python 选择合适python2.7及以上版本安装https://www.python.org/downloads/ 2.建立虚拟环境 这不是必须的,但是建议使用,为每个项目单独引入依赖, ...
- Django两天搭建个人博客
传送门:https://github.com/1417766861/django-blog(可直接运行,上面有步骤) 效果: 首页: 侧栏: 详情页面: 修改头像,资料,文章发布: 支持添加标签拖拽 ...
随机推荐
- Zookeeper管理多个HBase集群
zookeeper是hbase集群的"协调器".由于zookeeper的轻量级特性,因此我们可以将多个hbase集群共用一个zookeeper集群,以节约大量的服务器.多个hbas ...
- SharePoint 2007 列表页定制--4个默认页定制
以"简单的领导简介"为例,欢迎大家指正 背景:项目中需要有领导简介的模块,就开始制作领导简介,本来很简单,有一个列表就可以,然后在前台展示出来,但是客户看到我们的效果,尤其输入领导 ...
- linux下分割和重组文件
linux shell命令里的split和cat命令可以轻松完成这两个功能,举个例子来说,比如一个1GB大小的文件foo.zip,以100M为块分割: 分割: split -b 100M -d foo ...
- ubuntu14.04下安装rubinius测试原生线程
因为CRuby(MRI)本身不支持原生多线程,所以想试一下其他ruby解释器实现对原生多线程的支持.于是安装rubinius折腾一下:) 在rubinius官网下载2.4.1源代码,然后驾轻就熟首先b ...
- async & await 异步编程的一点巧方法
await 关键字不会创建新的线程,而是由Task任务或是FCL中的xxxAsync等方法创建的线程,而且这里创建的线程都是基于线程池创建的工作线程,属于后台线程. await关键字会阻塞/暂停调用它 ...
- C#中的var和dynamic
在理解var和dynamic关键字之前,让我们先了解一下编程语言的类别. C#中有两类编程语言: 静态类型语言类别 动态语言类别 静态类型语言 静态类型语言也被称为强类型语言.所谓强类型语言,通俗的讲 ...
- Java 故障安全异常处理
异常处理代码必须保证其故障安全机制,其中一条重要的规则如下: 在try-catch-finally块抛出的最后一个异常将会在调用堆栈中传递. 所有早期异常将会消失. 如果从一个catch或finall ...
- 无效类字符串:ProgID: Excel.Application
网上发现的方案是改注册表,其实用不着那么麻烦,找2种excel文件:xlsx和xls,把默认打开方式都换成你机器上有的程序就行,比如WPS Office的WPS 表格
- Pivotal开源基于PostgreSQL的数据库Greenplum
http://www.infoq.com/cn/news/2015/11/PostgreSQL-Pivotal 近日,Pivotal宣布开源大规模并行处理(MPP)数据库Greenplum,其架构是针 ...
- RESTful规范建议
RESTful概述 RESTful是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. REST是Representational State T ...