评论
# 根评论功能实现
urls.py
from django.conf.urls import url
from django.contrib import admin
from django.views.static import serve
from BBS import settings
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^register/', views.register), # -- 注册
url(r'^login/', views.login), # -- 登陆
url(r'^get_code/', views.get_code), # -- 获取验证码
url(r'^home/', views.home), # -- 首页
url(r'^logout/', views.logout), # -- 退出登陆
url(r'^set_pwd/', views.set_pwd), # -- 修改密码
# -- 点赞点踩功能
url(r'^up_or_down/$', views.up_or_down),
# -- 文章评论功能
url(r'^comment/$', views.comment),
# -- 个人站点 (有名分组)
url(r'^(?P<username>\w+)/$', views.site),
# -- 个人站点侧边栏筛选功能!
url(r'^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)', views.site),
# -- 开放对外访问的接口
url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
# -- 文章详情页
url(r'^(?P<username>\w+)/article/(?P<article_id>\d+)', views.article_detail),
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from app01 import models
from django.db.models import Count, F
from django.db.models.functions import TruncMonth
from django.db import transaction
import json
import hashlib
import random
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO, StringIO
def register(request):...
def get_random():...
def get_code(request):...
def login(request):...
def home(request):...
def logout(request):...
def set_pwd(request):...
def site(request, username, **kwargs):...
def article_detail(request, username, article_id):...
def up_or_down(request):...
def comment(request):
if request.method == "POST":
back_dic = {'code': 200, 'msg': ''}
article_id = request.POST.get('article_id')
content = request.POST.get('content')
# -- 验证用户是否登陆!
if not request.session.get('username'):
back_dic['code'] = 1018
back_dic['msg'] = "<a href='/login/' style='color: goldenrod'>请先登陆.</a>"
return JsonResponse(back_dic)
# -- 入库
# 在这里模拟下事务的使用.
with transaction.atomic():
# 1.操作文章表
article_obj = models.Article.objects.filter(pk=article_id).first()
if not article_obj.comment_num:
article_obj.comment_num = 1
article_obj.save()
else:
article_obj.comment_num += 1
article_obj.save()
# 2.操作评论表
models.Comment.objects.create(
content=content,
article_id=article_id,
user_id=request.session.get('id'))
back_dic['msg'] = '评论成功!'
return JsonResponse(back_dic)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
article_detail.html
{% extends 'site.html' %}
{% block content_9 %}
<h1>{{ article_obj.title }}</h1>
{# -- 点赞点踩样式开始 -- #}
<div style="display: flex;justify-content: flex-end;" ...>
{# -- 点赞点踩样式结束 -- #}
{# -- 文章内容开始 -- #}
<div class="article_content" ...>
{# -- 文章内容结束 -- #}
{# -- 评论楼开始 -- #}
{# -- 评论楼结束 -- #}
{# -- 评论样式开始 -- #}
<div style="margin-top: 10px" ...>
<p><span class="glyphicon glyphicon-envelope"></span> 发表评论</p>
<p><textarea name="" id="comment_content" cols="30" rows="5"></textarea></p>
<p>
<button class="btn btn-primary submit_comment">提交评论</button>
</p>
</div>
{# -- 评论样式结束 -- #}
{% endblock %}
{% block js %}
<script>
// 点赞点踩功能
$('.action').click(function () {...})
// 评论功能
$('.submit_comment').click(function () {
// 可以在这里面自定义属性,保存下再取
// <button aid="{{ article_obj.pk }}">提交评论</button>
let article_id = '{{ article_obj.pk }}'
let content = $('#comment_content').val()
if (!content) {
layer.msg('请来点咖啡/评论!')
return
}
// 发起ajax请求
$.ajax({
url: '/comment/',
type: 'post',
data: {
'article_id': article_id,
'content': content,
'csrfmiddlewaretoken': '{{ csrf_token }}',
},
success: function (res) {
if (res.code == 200) {
$('#comment_content').val('')
layer.msg(res.msg)
} else {
layer.msg(res.msg)
}
}
})
})
</script>
{% endblock %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 评论楼展示
在views.py的article_detail里修改添加以下代码.
def article_detail(request, username, article_id):
# -- 验证站点是否存在、文章是否存在 但凡有一个不存在,跳转404页面
# ... ...
# -- 左侧筛选功能的数据还是得再传一遍
# ... ...
# -- 查出所有的评论
comment_list = models.Comment.objects.filter(article__pk=article_id).all()
return render(request, 'article_detail.html', locals())
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
在article_detail.html里添加修改以下代码!
{# -- 评论楼开始 -- #}
<div style="margin-top: 10px">
<ul class="list-group">
{% for comment in comment_list %}
<li class="list-group-item">
<p>
<span># {{ forloop.counter }}楼 </span>
<span>{{ comment.create_time|date:'Y-m-d H:i' }}</span>
<span>{{ comment.user.username }}</span>
<span class="pull-right"><a href="" class="reply">回复</a></span>
</p>
<p>{{ comment.content }}</p>
</li>
{% endfor %}
</ul>
</div>
<div class="temp_comment"></div> {# 放临时评论的地方 #}
{# -- 评论楼结束 -- #}
$('.submit_comment').click(function () {
// 可以在这里面自定义属性,保存下再取
// <button aid="{{ article_obj.pk }}">提交评论</button>
let article_id = '{{ article_obj.pk }}'
let content = $('#comment_content').val()
if (!content) {
layer.msg('请来点咖啡/评论!')
return
}
// 发起ajax请求
$.ajax({
url: '/comment/',
type: 'post',
data: {
'article_id': article_id,
'content': content,
'csrfmiddlewaretoken': '{{ csrf_token }}',
},
success: function (res) {
if (res.code == 200) {
$('#comment_content').val('')
let username = '{{ request.session.username }}'
let html = `
<li class="list-group-item">
<p>
<span>${username}的评论:</span>
</p>
<p>${content}</p>
</li>
`
$('.temp_comment').append(html)
layer.msg(res.msg)
} else {
layer.msg(res.msg)
}
}
})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 子评论功能实现
代码太杂了,不想粘贴了.. 阐述下逻辑..
点击回复按钮,可以拿到当前评论的id,此id作为点击提交评论按钮时发生的ajax请求中的parent_id数据!!
在后台添加的评论数据就具备了parent_id,而不是Null..
注意一点的是,回复按钮点击事件里的变量,评论按钮的点击事件里也要用的话,将该变量设计为全局变量即可..
我麻了.. 真心不喜欢前端. ╮( ̄▽ ̄"")╭ 前端的展示惨不忍睹.. 略.
# 后台添加文章
先创建一个应用: startapp app02
并注册应用
在admin目录下创建分路由urls.py,在总路由里做路由分发! url(r'^app02/', include('app02.urls')),
app02/urls.py
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'^add_article/', views.add_article),
url(r'^article_list/', views.article_list),
]
1
2
3
4
5
6
7
2
3
4
5
6
7
app02/views.py
应该将输入的content内容进行过滤,过滤掉script标签,防止xss攻击!!!
使用正则可以,使用 bs4模块 更容易!!略.
from django.shortcuts import render, redirect, HttpResponse
from app01 import models
def add_article(request):
if request.method == "POST":
title = request.POST.get('title')
content = request.POST.get('content')
cate = request.POST.get('cate')
tag_list = request.POST.getlist('tag') # -- 接收多个
desc = content[0:100]
# -- 这里完善点,还需要分类的id和站点id,略.
article_obj = models.Article.objects.create(
title=title,
desc=desc,
content=content,
)
# -- 手动给第三张表添加数据,因为用不了add、set等方法
article_obj_list = []
# 批量添加.
# 当然可以一个个的添加
# models.Article2Tag.objects.create(article=article_obj, tag_id=i)
# models.Article2Tag.objects.create(article_id=article_obj.pk, tag_id=i)
for i in tag_list:
obj = models.Article2Tag(article=article_obj, tag_id=i)
article_obj_list.append(obj)
models.Article2Tag.objects.bulk_create(article_obj_list)
return redirect('/app02/article_list/')
# -- 用username=request.session.get('username')来筛选也行,但用主键更快.
userinfo = models.UserInfo.objects.filter(pk=request.session.get('id')).first()
# -- 必须得登陆
if not userinfo:
return render(request, 'error.html')
cate_list = models.Category.objects.filter(site__pk=userinfo.site.pk).all()
tag_list = models.Tag.objects.filter(site__pk=userinfo.site.pk).all()
return render(request, "admin/add_article.html", locals())
def article_list(request):
return HttpResponse('list')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
template/admin/add_article.html
添加内容那里可以使用富文本编辑框: kindeditor、百度富文本
去官网下载安装包,阅读使用文档进行相关的配置!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
{% load static %}
<script src="{% static 'layer-v3.5.1/layer/layer.js' %}"></script>
<title>Title</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-4">
<h2 class="text-center">添加文章</h2>
<form action="" method="post">
{% csrf_token %}
<p>标题: <input type="text" name="title" class="form-control"></p>
<p>内容: <textarea name="content" id="" cols="30" rows="10"></textarea></p>
<p>分类:
{% for cate in cate_list %}
{# 若不写value属性的值 选择后发送到后端的都是on,就不知道选的是哪个 #}
<input type="radio" name="cate" value="{{ cate.pk }}">{{ cate.name }}
{% endfor %}
</p>
<p>标签:
{% for tag in tag_list %}
{# 若不写value属性的值 选择后发送到后端的都是on,就不知道选的是哪个 #}
<input type="checkbox" name="tag" value="{{ tag.pk }}">{{ tag.name }}
{% endfor %}
</p>
<input type="submit" class="btn btn-success" value="发表">
</form>
</div>
</div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39