【Python】Django 0424 博客开发 018
目标效果:
html的表单变成django_form
在comment中创建forms.py文件,编写代码:
from django import formsfrom django.contrib.contenttypes.models import ContentType
from django.db.models import ObjectDoesNotExist
from ckeditor.widgets import CKEditorWidget
class CommentForm(forms.Form):
content_type = forms.CharField(widget=forms.HiddenInput)
object_id = forms.IntegerField(widget=forms.HiddenInput)
text = forms.CharField(widget=CKEditorWidget(config_name='comment_ckeditor'),
error_messages={'required': '评论内容不能为空'})
def __init__(self, *args, **kwargs):
if 'user' in kwargs:
self.user = kwargs.pop('user')
super(CommentForm, self).__init__(*args, **kwargs)
def clean(self):
# 判断用户是否登录
if self.user.is_authenticated:
self.cleaned_data['user'] = self.user
else:
raise forms.ValidationError('用户尚未登录')
# 评论对象验证
content_type = self.cleaned_data['content_type']
object_id = self.cleaned_data['object_id']
try:
model_class = ContentType.objects.get(model=content_type).model_class()
model_obj = model_class.objects.get(pk=object_id)
self.cleaned_data['content_object'] = model_obj
except ObjectDoesNotExist: # 不使用exceptions的原因时为了防止将任何错误都归因于评论对象不存在从而导致难以维护
raise forms.ValidationError('评论对象不存在')
return self.cleaned_data
在comment中的views.py中导入Comment并且在下面将该参数传递给前端,
from django.shortcuts import render, redirectfrom django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from django.http import JsonResponse
from .models import Comment
from .forms import CommentForm
def update_comment(request):
referer = request.META.get('HTTP_REFERER', reverse('home'))
comment_form = CommentForm(request.POST, user=request.user) # 实例化
data = {}
if comment_form.is_valid():
# 检查通过,保存数据
comment = Comment()
comment.user = comment_form.cleaned_data['user']
comment.text = comment_form.cleaned_data['text']
comment.content_object = comment_form.cleaned_data['content_object']
comment.save()
# 返回数据
data['status'] = 'SUCCESS'
data['username'] = comment.user.username
data['comment_time'] = comment.comment_time.strftime('%Y-%m-%d %H:%M:%S')
data['text'] = comment.text
else:
#return render(request, 'error.html', {'message': comment_form.errors, 'redirect_to': referer})
data['status'] = 'ERROR'
data['message'] = list(comment_form.errors.values())[0][0]
return JsonResponse(data)
然后再blog_detail中提价评论下面增加{{comment_form}}以加入渲染
<h3 class="comment-area-title">提交评论</h3>{% if user.is_authenticated %}
<form action="https://segmentfault.com/a/1190000038287203/{% url 'update_comment' %}" method="POST">
{% csrf_token %}
{{ comment_form }}
<div class="form-group">
<label for="comment_text">{{ user.username }},欢迎评论~</label>
修改blog/views.py中blog_detail
from comment.forms import CommentForm......
def blog_detail(request, blog_pk):
context['comment_form'] = CommentForm(initial={'content_type': blog_content_type.model, 'object_id': blog_pk})
效果如下:
两个框,而且文本编辑功能欠缺,我们优化并增加一下新功能:
将blog\_detail.html中的欢迎评论周围简化样式,并且优化:
新的
{# 删除和base中重复的内容,留下独有的内容,然后分别填充到下面的两个block中 #}{# 这是页面标题 #}
{% extends 'base.html' %}
{% block title %}{{ blog.title }}{% endblock %}{# 这里因为之前title被包起来了,所以直接用变量即可 #}
{% block nav_blog_active %}active{% endblock %}
{% load static %}
{% block header_extends %}
<link rel="stylesheet" href="https://segmentfault.com/a/1190000038287203/{% static 'blog/blog.css' %}">
<script type="text/javascript"ckeditor/ckeditor-init.js" %}"></script>
<script type="text/javascript"ckeditor/ckeditor/ckeditor.js" %}"></script>
{% endblock %}
{# 页面内容 #}
{% block content %}
<div class="container">
<div class="row">
<div class="col-xs-10 col-xs-offset-1">
<h3>{{ blog.title }}</h3>
<ul class="blog-info-description">
<li>作者:{{ blog.author }}</li>
<li>分类:<a href="https://segmentfault.com/a/1190000038287203/{% url 'blogs_with_type' blog.blog_type.pk %}">{{ blog.blog_type }}</a></li>
<li>发表日期:{{ blog.created_time|date:"Y-m-d H:i:s" }}</li>
<li>阅读量:({{ blog.get_read_num }})</li>
</ul>
<div class="blog-content">{{ blog.content|safe }}</div>
<div class="blog-more">
<p>上一篇:
{% if previous_blog %}
<a href="https://segmentfault.com/a/1190000038287203/{% url 'blog_detail' previous_blog.pk %}">{{ previous_blog.title }}</a>
{% else %}
没有了
{% endif %}
</p>
<p>下一篇:
{% if next_blog %}
<a href="https://segmentfault.com/a/1190000038287203/{% url 'blog_detail' next_blog.pk %}">{{ next_blog.title }}</a>
{% else %}
没有了
{% endif %}
</p>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-10 col-xs-offset-1">
<div class="comment-area">
<h3 class="comment-area-title">提交评论</h3>
{% if user.is_authenticated %}
<form id="comment_form" action="https://segmentfault.com/a/1190000038287203/{% url 'update_comment' %}" method="POST">
<label>{{ user.username }},欢迎评论~</label>
{% csrf_token %}
{% for field in comment_form %}
{{ field }}
{% endfor %}
<span id="comment_error" class="text-danger pull-left"></span>
<input type="submit" value="评论" class="btn btn-primary pull-right">
</form>
{% else %}
您尚未登录,登录之后方可评论~
<a class="btn btn-primary" href="https://segmentfault.com/a/1190000038287203/{% url 'login' %}?from={{ request.get_full_path }}">登录</a>
<span> or </span>
<a class="btn btn-danger" href="https://segmentfault.com/a/1190000038287203/{% url 'register' %}?from={{ request.get_full_path }}">注册</a>
{% endif %}
</div>
<div class="comment-area">
<h3 class="comment-area-title">评论列表</h3>
<div id="comment_list">
{% for comment in comments %}
<div>
{{ comment.user.username }}
({{ comment.comment_time|date:"Y-m-d H:i:s" }}):
{{ comment.text|safe }}
</div>
{% empty %}
暂无评论
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script_extends %}
<script type="text/javascript">
$("#comment_form").submit(function(){
// 判断是否为空
$("#comment_error").text('');
if(CKEDITOR.instances["id_text"].document.getBody().getText().trim()==''){
$("#comment_error").text('评论内容不能为空');
return false;
}
// 更新数据到textarea
CKEDITOR.instances['id_text'].updateElement();
// 异步提交
$.ajax({
url: "https://segmentfault.com/a/1190000038287203/{% url 'update_comment' %}",
type: 'POST',
data: $(this).serialize(),
cache: false,
success: function(data){
console.log(data);
if(data['status']=="SUCCESS"){
// 插入数据
var comment_html = '<div>' + data['username'] +
' (' + data['comment_time'] + '):' +
data['text'] + '</div>';
$("#comment_list").prepend(comment_html);
// 清空编辑框的内容
CKEDITOR.instances['id_text'].setData('');
}else{
// 显示错误信息
$("#comment_error").text(data['message']);
}
},
error: function(xhr){
console.log(xhr);
}
});
return false;
});
</script>
{% endblock %}
原来的:
<div class="row"> <div class="col-xs-10 col-xs-offset-1">
<div class="comment-area">
<h3 class="comment-area-title">提交评论</h3>
{% if user.is_authenticated %}
<form action="https://segmentfault.com/a/1190000038287203/{% url 'update_comment' %}" method="POST">
{% csrf_token %}
{{ comment_form }}
<div class="form-group">
<label for="comment_text">{{ user.username }},欢迎评论~</label>
<textarea id="comment_text" class="form-control" name="text" rows="4"></textarea>
{#使用input无法多行输入,换成textarea来写多行内容,使用bootstrap中的form-control对编辑区域和提交功能的性能优化#}
</div>
<input type="hidden" name="object_id" value="{{ blog.pk }}">
<input type="hidden" name="content_type" value="blog">
<input type="submit" value="评论" class="btn btn-primary">
</form>
{% else %}
您尚未登录,登录之后方可评论~
<a class="btn btn-primary" href="https://segmentfault.com/a/1190000038287203/{% url 'login' %}?from={{ request.get_full_path }}">登录</a>
<span> or </span>
<a class="btn btn-danger" href="https://segmentfault.com/a/1190000038287203/{% url 'register' %}?from={{ request.get_full_path }}">注册</a>
{% endif %}
</div>
<div class="comment-area">
<h3 class="comment-area-title">评论列表</h3>
{% for comment in comments %}
<div>
{{ comment.user.username }}
({{ comment.comment_time|date:"Y-m-d H:n:s" }}):
{{ comment.text }}
</div>
{% empty %}
暂无评论
{% endfor %}
</div>
</div>
</div>
在settings.中加入
CKEDITOR_CONFIGS = { 'comment_ckeditor': {
'toolbar': 'custom',
'toolbar_custom': [
['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript'],
["TextColor", "BGColor", 'RemoveFormat'],
['NumberedList', 'BulletedList'],
['Link', 'Unlink'],
["Smiley", "SpecialChar", 'Blockquote'],
],
'width': 'auto',
'height': '180',
'tabSpaces': 4,
'removePlugins': 'elementspath',
'resize_enabled': False,
}
}
然后增加blog.css样式
div.django-ckeditor-widget { width: 100%;
}
修改blog.forms.py中的CommentFomr类下面的text内容
text = forms.CharField(widget=CKEditorWidget(config_name='comment_ckeditor'), error_messages={'required': '评论内容不能为空'})
给comment/models.py中增加袁磊,使其按照评论时间倒序排列:
class Meta: ordering = ['-comment_time']
以上是 【Python】Django 0424 博客开发 018 的全部内容, 来源链接: utcz.com/a/75197.html