python 全栈开发,Day82(点赞和踩灭,用户评论)

一、点赞和踩灭

样式

先来做样式,修改article_detail.html,增加div_digg的div

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>

{% endblock %}

View Code

在static-->css目录下,创建文件article_detail.css

#div_digg {
    float: right;
    margin-bottom: 10px;
    margin-right: 30px;
    font-size: 12px;
     125px;
    text-align: center;
    margin-top: 10px;
}

.diggit {
float: left;
46px;
height: 52px;
background: url("/static/img/upup.gif") no-repeat;
text
-align: center;
cursor: pointer;
margin
-top: 2px;
padding
-top: 5px;
}

.buryit {
float: right;
margin-left: 20px;
46px;
height: 52px;
background: url(
"/static/img/downdown.gif") no-repeat;
text
-align: center;
cursor: pointer;
margin
-top: 2px;
padding
-top: 5px;
}

View Code

从博客园拷贝2个图片到static-->img目录下

修改base.html,引入article_detail.css

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="shortcut icon" href="https://common.cnblogs.com/favicon.ico" type="image/x-icon"/>
    {#公共样式#}
    <link rel="stylesheet" href="/static/css/theme/common.css">
    {#个人站点主题样式#}
    <link rel="stylesheet" href="/static/css/theme/{{ blog.theme }}">
    {#bootstrap#}
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
    <script src="/static/js/jquery.js"></script>
    <script src="/static/bootstrap/js/bootstrap.js"></script>
    {#文章详情#}
    <link rel="stylesheet" href="/static/css/article_detail.css">

</head>
<body>
<div class="header">
<p class="title">{{ blog.title }}</p>
</div>

<div class="container-fluid">
<div class="row">
<div class="col-md-3">
{
#加载自定义标签模块#}
{% load my_tags %}
{
#调用get_query_data标签,它返回left_region.html,是已经被渲染过的文件#}
{% get_query_data username %}
</div>
<div class="col-md-9">

        {</span>% block content %<span style="color: #000000;">}

        {</span>% endblock %<span style="color: #000000;">}

    </span>&lt;/div&gt;
&lt;/div&gt;

</div>

</body>
</html>

View Code

点击一篇文章:http://127.0.0.1:8000/xiao/articles/5/

拉到最下面,右侧效果如下:

绑定事件

推荐和反对有2个按钮,要绑定2个事件吗?答案是可以,但是不推荐使用!为什么呢?

因为会造成大量代码重复!这2个按钮需要发送的文章id和用户id是一样的,唯一不同的就是:一个是推荐,一个是反对。

修改article_detail.html增加div,测试js代码

注意:在base.html中已经导入了jquery

hasClass() 方法检查被选元素是否包含指定的 class。它返回True和False

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>
<script>
$(
".action").click(function () {
{
#hasClass() 方法检查被选元素是否包含指定的 class#}
var is_up = $(this).hasClass("diggit");
alert(is_up);

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

刷新网页,点击文章右下角的推荐,提示true

点击反对,提示false

发送ajax请求

数据分析

到底是用get还是post呢?有一个规范:查询用get,更改用post

查看blog_articleupdown表,这个是点赞表。插入一条记录,需要3个参数,分别是是否点赞、文章id、用户id

注意:这个用户id是当前登录用户,不是文章作者!

由于在视图函数中,有一个全局变量request.user。它是用户登录之后,才有的!所以这个用户id,不需要传。

只需要传2个值就可以了,分别是是否点赞和文章id。

在article_detail.html中,已经有一个article_obj,它是一个model对象,那么就可以得到文章id。

是否点赞,通过js代码中的is_up变量,也可以知道。

所以发送的数据,不需要使用标签选择器来获取。直接使用即可!

操作流程

  1. 用户点击推荐或者反对,触发点击事件
  2. 发送ajax请求给服务器
  3. 服务器接收参数,生成一条点赞或者踩灭的记录
  4. 服务器将返回结果响应给浏览器,浏览器中的ajax代码的success中的data接收响应体
  5. ajax对响应的数据做判断,操作DOM,显示给用户看!

服务器处理

修改urls.py,增加一个路径digg

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    path('', views.index),
    #点赞或者踩灭
    path('digg/', views.digg),
</span><span style="color: #008000;">#</span><span style="color: #008000;">文章详情</span>
re_path(<span style="color: #800000;">'</span><span style="color: #800000;">(?P&lt;username&gt;w+)/articles/(?P&lt;article_id&gt;d+)/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, views.article_detail),
</span><span style="color: #008000;">#</span><span style="color: #008000;"> 跳转</span>
re_path(<span style="color: #800000;">'</span><span style="color: #800000;">(?P&lt;username&gt;w+)/(?P&lt;condition&gt;category|tag|achrive)/(?P&lt;params&gt;.*)/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, views.homesite),
</span><span style="color: #008000;">#</span><span style="color: #008000;"> 个人站点</span>
re_path(<span style="color: #800000;">'</span><span style="color: #800000;">(?P&lt;username&gt;w+)/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, views.homesite),

]

View Code

注意:digg要放到文章详情的上面

修改article_detail.html

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>
{
% csrf_token %}
<script>
$(
".action").click(function () {
{
#hasClass() 方法检查被选元素是否包含指定的 class#}
var is_up = $(this).hasClass("diggit");
{
#判断是否登录#}
if ("{{ request.user.username }}") {
$.ajax({
url:
"/digg/",
type:
"post",
data: {
is_up: is_up,
article_id:
"{{ article_obj.pk }}",
csrfmiddlewaretoken: $(
"[name='csrfmiddlewaretoken']").val()
},
success: function (data) {
console.log(data);
console.log(typeof data);

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

修改views.py,增加视图函数digg

注意:导入2个模块

import json
from django.http import JsonResponse

视图函数如下:

from django.shortcuts import render,HttpResponse,redirect
from django.contrib import auth
from blog.models import Article,UserInfo,Blog,Category,Tag,ArticleUpDown
from django.db.models import Sum,Avg,Max,Min,Count
from django.db.models import F
import json
from django.http import JsonResponse

# Create your views here.
def login(request):

</span><span style="color: #0000ff;">if</span> request.method==<span style="color: #800000;">"</span><span style="color: #800000;">POST</span><span style="color: #800000;">"</span><span style="color: #000000;">:
    user</span>=request.POST.get(<span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    pwd</span>=request.POST.get(<span style="color: #800000;">"</span><span style="color: #800000;">pwd</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> 用户验证成功,返回user对象,否则返回None</span>
    user=auth.authenticate(username=user,password=<span style="color: #000000;">pwd)
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> user:
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> 登录,注册session</span>
        <span style="color: #008000;">#</span><span style="color: #008000;"> 全局变量 request.user=当前登陆对象(session中)</span>

auth.login(request,user)
return redirect("/index/")

</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">"</span><span style="color: #800000;">login.html</span><span style="color: #800000;">"</span><span style="color: #000000;">)

def index(request):
article_list
=Article.objects.all()
return render(request,"index.html",{"article_list":article_list})

def logout(request): # 注销
auth.logout(request)
return redirect("/index/")

def query_current_site(request,username): # 查询当前站点的博客标题
# 查询当前站点的用户对象
user = UserInfo.objects.filter(username=username).first()
if not user:
return render(request, "not_found.html")
# 查询当前站点对象
blog = user.blog
return blog

def homesite(request,username,**kwargs): # 个人站点主页
print("kwargs", kwargs)

blog </span>=<span style="color: #000000;"> query_current_site(request,username)

</span><span style="color: #008000;">#</span><span style="color: #008000;"> 查询当前用户发布的所有文章</span>
<span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span><span style="color: #000000;"> kwargs:
    article_list </span>= Article.objects.filter(user__username=<span style="color: #000000;">username)
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    condition </span>= kwargs.get(<span style="color: #800000;">"</span><span style="color: #800000;">condition</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    params </span>= kwargs.get(<span style="color: #800000;">"</span><span style="color: #800000;">params</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    </span><span style="color: #008000;">#</span><span style="color: #008000;">判断分类、随笔、归档</span>
    <span style="color: #0000ff;">if</span> condition == <span style="color: #800000;">"</span><span style="color: #800000;">category</span><span style="color: #800000;">"</span><span style="color: #000000;">:
        article_list </span>= Article.objects.filter(user__username=username).filter(category__title=<span style="color: #000000;">params)
    </span><span style="color: #0000ff;">elif</span> condition == <span style="color: #800000;">"</span><span style="color: #800000;">tag</span><span style="color: #800000;">"</span><span style="color: #000000;">:
        article_list </span>= Article.objects.filter(user__username=username).filter(tags__title=<span style="color: #000000;">params)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        year, month </span>= params.split(<span style="color: #800000;">"</span><span style="color: #800000;">/</span><span style="color: #800000;">"</span><span style="color: #000000;">)
        article_list </span>= Article.objects.filter(user__username=username).filter(create_time__year=<span style="color: #000000;">year,
                                                                              create_time__month</span>=<span style="color: #000000;">month)
</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">"</span><span style="color: #800000;">homesite.html</span><span style="color: #800000;">"</span>,{<span style="color: #800000;">"</span><span style="color: #800000;">blog</span><span style="color: #800000;">"</span>:blog,<span style="color: #800000;">"</span><span style="color: #800000;">username</span><span style="color: #800000;">"</span>:username,<span style="color: #800000;">"</span><span style="color: #800000;">article_list</span><span style="color: #800000;">"</span><span style="color: #000000;">:article_list})

def article_detail(request,username,article_id):
blog
= query_current_site(request,username)

</span><span style="color: #008000;">#</span><span style="color: #008000;">查询指定id的文章</span>
article_obj = Article.objects.filter(pk=<span style="color: #000000;">article_id).first()
user_id </span>= UserInfo.objects.filter(username=<span style="color: #000000;">username).first().nid

</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">'</span><span style="color: #800000;">article_detail.html</span><span style="color: #800000;">'</span>,{<span style="color: #800000;">"</span><span style="color: #800000;">blog</span><span style="color: #800000;">"</span>:blog,<span style="color: #800000;">"</span><span style="color: #800000;">username</span><span style="color: #800000;">"</span>:username,<span style="color: #800000;">'</span><span style="color: #800000;">article_obj</span><span style="color: #800000;">'</span>:article_obj,<span style="color: #800000;">"</span><span style="color: #800000;">user_id</span><span style="color: #800000;">"</span><span style="color: #000000;">:user_id})

def digg(request):
print(request.POST)
if request.method == "POST":
#ajax发送的过来的true和false是字符串,使用json反序列化得到布尔值
is_up = json.loads(request.POST.get("is_up"))
article_id
= request.POST.get("article_id")
user_id
= request.user.pk

    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: True, <span style="color: #800000;">"</span><span style="color: #800000;">msg</span><span style="color: #800000;">"</span>: None}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">判断当前登录用户是否对这篇文章做过点赞或者踩灭操作</span>
    obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=<span style="color: #000000;">article_id).first()
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> obj:
        response[</span><span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>] = False  <span style="color: #008000;">#</span><span style="color: #008000;"> 更改状态</span>
    <span style="color: #0000ff;">else</span><span style="color: #000000;">:
        </span><span style="color: #008000;">#</span><span style="color: #008000;">插入一条记录</span>
        new_obj = ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=<span style="color: #000000;">is_up)

    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> JsonResponse(response)

</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span>)</pre>
View Code

json处理问题

ajax发送的过来的true和false是字符串,使用json反序列化得到布尔值

json支持7种数据格式,其中true和false是其中2种。那么反序列化之后,会得到一个布尔值。

为什么一定要反序列化呢?因为...create(...is_up=is_up) 等式右边的值,非空。那么ORM会认为是True!

所以不管ajax传过来的是true和falase,它都是字符串,那么ORM执行时,始终都是True

JsonResponse

JsonResponse对象是HttpRespon的子类,它主要和父类的区别在于:

1.它的默认Content-Type 被设置为: application/json

2.第一个参数,data应该是一个字典类型,如果不是字典,抛出 TypeError的异常

它返回json数据,那么ajax接收时,不需要反序列化,可以直接使用!

刷新网页,点击右侧的推荐,查看浏览器控制台

查看blog_articleupdown表记录,发现多了一条记录

查看Pycharm控制台输出:

<QueryDict: {'article_id': ['6'], 'csrfmiddlewaretoken': ['JgLyFpVgp92Rs8ppPCd2pm9jVj6z8bo9KSsMwKnakpB6CwTCT1K58v2JHLeR5ejN'], 'is_up': ['true']}>

判断用户之前的操作

当用户第一次点击推荐时,直接将数字加1。再次点击时,提示您已经推荐过!再次点击返回时,也提示您已经推荐过。

同理,当用户对一篇点击返回后。之后不论是点击推荐还是反对,都会提示您已经反对过!

不可以取消推荐或者反对!

修改views.py,获取上一次操作的记录

def digg(request):
    print(request.POST)
    if request.method == "POST":
        #ajax发送的过来的true和false是字符串,使用json反序列化得到布尔值
        is_up = json.loads(request.POST.get("is_up"))
        article_id = request.POST.get("article_id")
        user_id = request.user.pk
    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: True, <span style="color: #800000;">"</span><span style="color: #800000;">msg</span><span style="color: #800000;">"</span>: None}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">判断当前登录用户是否对这篇文章做过点赞或者踩灭操作</span>
    obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=<span style="color: #000000;">article_id).first()
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> obj:
        response[</span><span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>] = False  <span style="color: #008000;">#</span><span style="color: #008000;"> 更改状态</span>
        response[<span style="color: #800000;">"</span><span style="color: #800000;">handled</span><span style="color: #800000;">"</span>] = obj.is_up  <span style="color: #008000;">#</span><span style="color: #008000;"> 获取之前的操作,返回true或者false</span>
        <span style="color: #0000ff;">print</span><span style="color: #000000;">(obj.is_up)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        </span><span style="color: #008000;">#</span><span style="color: #008000;">插入一条记录</span>
        new_obj = ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=<span style="color: #000000;">is_up)

    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> JsonResponse(response)

</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span>)</pre>
View Code

修改article_detail.html的js代码

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>
{
% csrf_token %}
<script>
$(
".action").click(function () {
{
#hasClass() 方法检查被选元素是否包含指定的 class#}
var is_up = $(this).hasClass("diggit");
{
#判断是否登录#}
if ("{{ request.user.username }}") {
$.ajax({
url:
"/digg/",
type:
"post",
data: {
is_up: is_up,
article_id:
"{{ article_obj.pk }}",
csrfmiddlewaretoken: $(
"[name='csrfmiddlewaretoken']").val()
},
success: function (data) {
console.log(data);
console.log(typeof data);
if (data.state) {
//提交成功
}
else {
if (data.handled) { //判断之前的操作记录
$(
"#digg_tips").html("您已经推荐过!")
}
else {
$(
"#digg_tips").html("您已经反对过!")
}
}

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

修改static-->css目录下的article_detail.css,增加样式

#div_digg {
    float: right;
    margin-bottom: 10px;
    margin-right: 30px;
    font-size: 12px;
     125px;
    text-align: center;
    margin-top: 10px;
}

.diggit {
float: left;
46px;
height: 52px;
background: url("/static/img/upup.gif") no-repeat;
text
-align: center;
cursor: pointer;
margin
-top: 2px;
padding
-top: 5px;
}

.buryit {
float: right;
margin-left: 20px;
46px;
height: 52px;
background: url(
"/static/img/downdown.gif") no-repeat;
text
-align: center;
cursor: pointer;
margin
-top: 2px;
padding
-top: 5px;
}
.clear {
clear: both;
}

#digg_tips{
color: red;
}

View Code

重启django项目,页面强制刷新几次!

再次点击,提示已经点过了

修改article_detail.html的js代码,增加动态效果,1秒后,清空红色文字

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>
{
% csrf_token %}
<script>
$(
".action").click(function () {
{
#hasClass() 方法检查被选元素是否包含指定的 class#}
var is_up = $(this).hasClass("diggit");
{
#判断是否登录#}
if ("{{ request.user.username }}") {
$.ajax({
url:
"/digg/",
type:
"post",
data: {
is_up: is_up,
article_id:
"{{ article_obj.pk }}",
csrfmiddlewaretoken: $(
"[name='csrfmiddlewaretoken']").val()
},
success: function (data) {
console.log(data);
console.log(typeof data);
if (data.state) {
//提交成功
}
else {
if (data.handled) { //判断之前的操作记录
$(
"#digg_tips").html("您已经推荐过!")
}
else {
$(
"#digg_tips").html("您已经反对过!")
}
setTimeout(function () {
$(
"#digg_tips").html("") //清空提示文字
},
1000)
}

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

效果如下:

更新文章表

blog_articleupdown表有一个联合唯一索引,即使重复点击,也不会增加记录!

blog_article表有一个up_count和down_count字段,分别表示推荐和反对的计数。

那么这2个字段,也需要同时更新。在原有数值的基础上加1,需要使用F查询!

导入F模块,完整代码如下:

def digg(request):
    print(request.POST)
    if request.method == "POST":
        #ajax发送的过来的true和false是字符串,使用json反序列化得到布尔值
        is_up = json.loads(request.POST.get("is_up"))
        article_id = request.POST.get("article_id")
        user_id = request.user.pk
    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: True, <span style="color: #800000;">"</span><span style="color: #800000;">msg</span><span style="color: #800000;">"</span>: None}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">判断当前登录用户是否对这篇文章做过点赞或者踩灭操作</span>
    obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=<span style="color: #000000;">article_id).first()
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> obj:
        response[</span><span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>] = False  <span style="color: #008000;">#</span><span style="color: #008000;"> 更改状态</span>
        response[<span style="color: #800000;">"</span><span style="color: #800000;">handled</span><span style="color: #800000;">"</span>] = obj.is_up  <span style="color: #008000;">#</span><span style="color: #008000;"> 获取之前的操作,返回true或者false</span>
        <span style="color: #0000ff;">print</span><span style="color: #000000;">(obj.is_up)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        </span><span style="color: #008000;">#</span><span style="color: #008000;">插入一条记录</span>
        new_obj = ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=<span style="color: #000000;">is_up)
        </span><span style="color: #0000ff;">if</span> is_up: <span style="color: #008000;">#</span><span style="color: #008000;"> 判断为推荐</span>
            Article.objects.filter(pk=article_id).update(up_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">up_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)
        </span><span style="color: #0000ff;">else</span>: <span style="color: #008000;">#</span><span style="color: #008000;"> 反对</span>
            Article.objects.filter(pk=article_id).update(down_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">down_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)

    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> JsonResponse(response)

</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span>)</pre>
View Code

清空blog_articleupdown表记录

访问网页,重新点击。再次刷新页面,那么值就会更新了!

网页实时展示

上面已经实现了,点击之后,更新数据库。但是需要刷新网页,才会有效果。想要用户能实时看到数字,需要进行DOM操作。

获取网页原有的值,进行加1。最后进行DOM操作,展示给用户看!

修改article_detail.html的js代码

注意:js是弱类型语言,获取到值时,不能直接进行加法,需要强制转换才行!

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>
{
% csrf_token %}
<script>
$(
".action").click(function () {
{
#hasClass() 方法检查被选元素是否包含指定的 class#}
var is_up = $(this).hasClass("diggit");
{
#获取提示的span标签#}
var _this= $(this).children("span");
{
#判断是否登录#}
if ("{{ request.user.username }}") {
$.ajax({
url:
"/digg/",
type:
"post",
data: {
is_up: is_up,
article_id:
"{{ article_obj.pk }}",
csrfmiddlewaretoken: $(
"[name='csrfmiddlewaretoken']").val()
},
success: function (data) {
console.log(data);
console.log(typeof data);
if (data.state) {
//提交成功
var val
=_this.text(); //获取text值
//在原有的基础上加1。注意:一定要进行类型转换
_this.text(parseInt(val)
+1)
}
else {
if (data.handled) { //判断之前的操作记录
$(
"#digg_tips").html("您已经推荐过!")
}
else {
$(
"#digg_tips").html("您已经反对过!")
}
setTimeout(function () {
$(
"#digg_tips").html("") //清空提示文字
},
1000)
}

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

清空blog_articleupdown表记录

将blog_article表的相关字段设置为0

访问网页,重新点击,效果如下:

优化js代码

将if判断部分,改成三元运算

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>
{
% csrf_token %}
<script>
$(
".action").click(function () {
{
#hasClass() 方法检查被选元素是否包含指定的 class#}
var is_up = $(this).hasClass("diggit");
{
#获取提示的span标签#}
var _this = $(this).children("span");
{
#判断是否登录#}
if ("{{ request.user.username }}") {
$.ajax({
url:
"/digg/",
type:
"post",
data: {
is_up: is_up,
article_id:
"{{ article_obj.pk }}",
csrfmiddlewaretoken: $(
"[name='csrfmiddlewaretoken']").val()
},
success: function (data) {
console.log(data);
console.log(typeof data);
if (data.state) {
//提交成功
var val
= _this.text(); //获取text值
//在原有的基础上加1。注意:一定要进行类型转换
_this.text(parseInt(val)
+ 1)
}
else {
// 重复提交
var val
= data.handled ? "您已经推荐过!" : "您已经反对过!";
$(
"#digg_tips").html(val);
setTimeout(function () {
$(
"#digg_tips").html("") //清空提示文字
},
1000)
}

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

事务

是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。

在上面的例子,点赞时,需要更新2个表。一个是blog_articleupdown表,一个是blog_article表。

如果有一个表没有更新,那么就会产生脏数据!为了避免这个问题,需要使用事务!

举例:模拟异常情况

修改digg视图函数,模拟异常

def digg(request):
    print(request.POST)
    if request.method == "POST":
        #ajax发送的过来的true和false是字符串,使用json反序列化得到布尔值
        is_up = json.loads(request.POST.get("is_up"))
        article_id = request.POST.get("article_id")
        user_id = request.user.pk
    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: True, <span style="color: #800000;">"</span><span style="color: #800000;">msg</span><span style="color: #800000;">"</span>: None}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">判断当前登录用户是否对这篇文章做过点赞或者踩灭操作</span>
    obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=<span style="color: #000000;">article_id).first()
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> obj:
        response[</span><span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>] = False  <span style="color: #008000;">#</span><span style="color: #008000;"> 更改状态</span>
        response[<span style="color: #800000;">"</span><span style="color: #800000;">handled</span><span style="color: #800000;">"</span>] = obj.is_up  <span style="color: #008000;">#</span><span style="color: #008000;"> 获取之前的操作,返回true或者false</span>
        <span style="color: #0000ff;">print</span><span style="color: #000000;">(obj.is_up)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        </span><span style="color: #008000;">#</span><span style="color: #008000;">插入一条记录</span>
        new_obj = ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=<span style="color: #000000;">is_up)
        ask  </span><span style="color: #008000;">#</span><span style="color: #008000;"> 这一行故意出错</span>
        <span style="color: #0000ff;">if</span> is_up: <span style="color: #008000;">#</span><span style="color: #008000;"> 判断为推荐</span>
            Article.objects.filter(pk=article_id).update(up_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">up_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)
        </span><span style="color: #0000ff;">else</span>: <span style="color: #008000;">#</span><span style="color: #008000;"> 反对</span>
            Article.objects.filter(pk=article_id).update(down_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">down_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)

    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> JsonResponse(response)

</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span>)</pre>
View Code

清空blog_articleupdown表,将blog_article表的up_count和down_count字段设置为0

刷新页面,重新点击,打开浏览器工具-->network

出行了500错误

 查看blog_articleupdown表,多了一条记录

 

查看blog_article表,对应文章的up_count字段,发现还是为0

使用事务

修改digg视图函数,导入模块transaction。

使用语法很简单,将相关原子操作的代码直接tab一下,就可以了

完整代码如下:

from django.shortcuts import render,HttpResponse,redirect
from django.contrib import auth
from blog.models import Article,UserInfo,Blog,Category,Tag,ArticleUpDown
from django.db.models import Sum,Avg,Max,Min,Count
from django.db.models import F
import json
from django.http import JsonResponse
from django.db import transaction

# Create your views here.
def login(request):

</span><span style="color: #0000ff;">if</span> request.method==<span style="color: #800000;">"</span><span style="color: #800000;">POST</span><span style="color: #800000;">"</span><span style="color: #000000;">:
    user</span>=request.POST.get(<span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    pwd</span>=request.POST.get(<span style="color: #800000;">"</span><span style="color: #800000;">pwd</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> 用户验证成功,返回user对象,否则返回None</span>
    user=auth.authenticate(username=user,password=<span style="color: #000000;">pwd)
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> user:
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> 登录,注册session</span>
        <span style="color: #008000;">#</span><span style="color: #008000;"> 全局变量 request.user=当前登陆对象(session中)</span>

auth.login(request,user)
return redirect("/index/")

</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">"</span><span style="color: #800000;">login.html</span><span style="color: #800000;">"</span><span style="color: #000000;">)

def index(request):
article_list
=Article.objects.all()
return render(request,"index.html",{"article_list":article_list})

def logout(request): # 注销
auth.logout(request)
return redirect("/index/")

def query_current_site(request,username): # 查询当前站点的博客标题
# 查询当前站点的用户对象
user = UserInfo.objects.filter(username=username).first()
if not user:
return render(request, "not_found.html")
# 查询当前站点对象
blog = user.blog
return blog

def homesite(request,username,**kwargs): # 个人站点主页
print("kwargs", kwargs)

blog </span>=<span style="color: #000000;"> query_current_site(request,username)

</span><span style="color: #008000;">#</span><span style="color: #008000;"> 查询当前用户发布的所有文章</span>
<span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span><span style="color: #000000;"> kwargs:
    article_list </span>= Article.objects.filter(user__username=<span style="color: #000000;">username)
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    condition </span>= kwargs.get(<span style="color: #800000;">"</span><span style="color: #800000;">condition</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    params </span>= kwargs.get(<span style="color: #800000;">"</span><span style="color: #800000;">params</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    </span><span style="color: #008000;">#</span><span style="color: #008000;">判断分类、随笔、归档</span>
    <span style="color: #0000ff;">if</span> condition == <span style="color: #800000;">"</span><span style="color: #800000;">category</span><span style="color: #800000;">"</span><span style="color: #000000;">:
        article_list </span>= Article.objects.filter(user__username=username).filter(category__title=<span style="color: #000000;">params)
    </span><span style="color: #0000ff;">elif</span> condition == <span style="color: #800000;">"</span><span style="color: #800000;">tag</span><span style="color: #800000;">"</span><span style="color: #000000;">:
        article_list </span>= Article.objects.filter(user__username=username).filter(tags__title=<span style="color: #000000;">params)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        year, month </span>= params.split(<span style="color: #800000;">"</span><span style="color: #800000;">/</span><span style="color: #800000;">"</span><span style="color: #000000;">)
        article_list </span>= Article.objects.filter(user__username=username).filter(create_time__year=<span style="color: #000000;">year,
                                                                              create_time__month</span>=<span style="color: #000000;">month)
</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">"</span><span style="color: #800000;">homesite.html</span><span style="color: #800000;">"</span>,{<span style="color: #800000;">"</span><span style="color: #800000;">blog</span><span style="color: #800000;">"</span>:blog,<span style="color: #800000;">"</span><span style="color: #800000;">username</span><span style="color: #800000;">"</span>:username,<span style="color: #800000;">"</span><span style="color: #800000;">article_list</span><span style="color: #800000;">"</span><span style="color: #000000;">:article_list})

def article_detail(request,username,article_id):
blog
= query_current_site(request,username)

</span><span style="color: #008000;">#</span><span style="color: #008000;">查询指定id的文章</span>
article_obj = Article.objects.filter(pk=<span style="color: #000000;">article_id).first()
user_id </span>= UserInfo.objects.filter(username=<span style="color: #000000;">username).first().nid

</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">'</span><span style="color: #800000;">article_detail.html</span><span style="color: #800000;">'</span>,{<span style="color: #800000;">"</span><span style="color: #800000;">blog</span><span style="color: #800000;">"</span>:blog,<span style="color: #800000;">"</span><span style="color: #800000;">username</span><span style="color: #800000;">"</span>:username,<span style="color: #800000;">'</span><span style="color: #800000;">article_obj</span><span style="color: #800000;">'</span>:article_obj,<span style="color: #800000;">"</span><span style="color: #800000;">user_id</span><span style="color: #800000;">"</span><span style="color: #000000;">:user_id})

def digg(request):
print(request.POST)
if request.method == "POST":
#ajax发送的过来的true和false是字符串,使用json反序列化得到布尔值
is_up = json.loads(request.POST.get("is_up"))
article_id
= request.POST.get("article_id")
user_id
= request.user.pk

    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: True, <span style="color: #800000;">"</span><span style="color: #800000;">msg</span><span style="color: #800000;">"</span>: None}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">判断当前登录用户是否对这篇文章做过点赞或者踩灭操作</span>
    obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=<span style="color: #000000;">article_id).first()
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> obj:
        response[</span><span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>] = False  <span style="color: #008000;">#</span><span style="color: #008000;"> 更改状态</span>
        response[<span style="color: #800000;">"</span><span style="color: #800000;">handled</span><span style="color: #800000;">"</span>] = obj.is_up  <span style="color: #008000;">#</span><span style="color: #008000;"> 获取之前的操作,返回true或者false</span>
        <span style="color: #0000ff;">print</span><span style="color: #000000;">(obj.is_up)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        with transaction.atomic():
            </span><span style="color: #008000;">#</span><span style="color: #008000;">插入一条记录</span>
            new_obj = ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=<span style="color: #000000;">is_up)
            ask  </span><span style="color: #008000;">#</span><span style="color: #008000;"> 模拟异常</span>
            <span style="color: #0000ff;">if</span> is_up: <span style="color: #008000;">#</span><span style="color: #008000;"> 判断为推荐</span>
                Article.objects.filter(pk=article_id).update(up_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">up_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)
            </span><span style="color: #0000ff;">else</span>: <span style="color: #008000;">#</span><span style="color: #008000;"> 反对</span>
                Article.objects.filter(pk=article_id).update(down_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">down_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)

    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> JsonResponse(response)

</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span>)</pre>
View Code

清空blog_articleupdown表

刷新页面,重新点击,再一次返回500错误

查看blog_articleupdown表,发现并没增加一条记录。

 

这样就比较合理了!删除异常代码

def digg(request):
    print(request.POST)
    if request.method == "POST":
        #ajax发送的过来的true和false是字符串,使用json反序列化得到布尔值
        is_up = json.loads(request.POST.get("is_up"))
        article_id = request.POST.get("article_id")
        user_id = request.user.pk
    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: True, <span style="color: #800000;">"</span><span style="color: #800000;">msg</span><span style="color: #800000;">"</span>: None}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">判断当前登录用户是否对这篇文章做过点赞或者踩灭操作</span>
    obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=<span style="color: #000000;">article_id).first()
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> obj:
        response[</span><span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>] = False  <span style="color: #008000;">#</span><span style="color: #008000;"> 更改状态</span>
        response[<span style="color: #800000;">"</span><span style="color: #800000;">handled</span><span style="color: #800000;">"</span>] = obj.is_up  <span style="color: #008000;">#</span><span style="color: #008000;"> 获取之前的操作,返回true或者false</span>
        <span style="color: #0000ff;">print</span><span style="color: #000000;">(obj.is_up)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        with transaction.atomic():
            </span><span style="color: #008000;">#</span><span style="color: #008000;">插入一条记录</span>
            new_obj = ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=<span style="color: #000000;">is_up)
            </span><span style="color: #0000ff;">if</span> is_up: <span style="color: #008000;">#</span><span style="color: #008000;"> 判断为推荐</span>
                Article.objects.filter(pk=article_id).update(up_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">up_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)
            </span><span style="color: #0000ff;">else</span>: <span style="color: #008000;">#</span><span style="color: #008000;"> 反对</span>
                Article.objects.filter(pk=article_id).update(down_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">down_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)

    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> JsonResponse(response)

</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span>)</pre>
View Code

刷新页面,重新点击

查看blog_articleupdown表,发现增加了一条记录。

查看blog_article表,对应文章的up_count字段,发现为1了!

事务用起来很简单,是因为django把复杂的逻辑给封装好了!
有时间的小伙伴,还可以加一个需求,自己不能给自己点赞!

二、用户评论

评论样式

先写html的样式代码

修改article_detail.html

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
<div class="clearfix"></div>

    &lt;div <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">comment</span><span style="color: #800000;">"</span>&gt;
        &lt;p&gt;评论列表&lt;/p&gt;
        &lt;ul <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">comment_list list-group</span><span style="color: #800000;">"</span>&gt;<span style="color: #000000;">
            {</span>% <span style="color: #0000ff;">for</span> comment <span style="color: #0000ff;">in</span> comment_list %<span style="color: #000000;">}
            </span>&lt;li <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">list-group-item</span><span style="color: #800000;">"</span>&gt;
               &lt;div&gt;
                   &lt;a href=<span style="color: #800000;">""</span>&gt;<span style="color: #008000;">#</span><span style="color: #008000;">{{ forloop.counter }}楼&lt;/a&gt;&amp;nbsp;&amp;nbsp;</span>
                   &lt;span <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">small</span><span style="color: #800000;">"</span>&gt;{{ comment.create_time|date:<span style="color: #800000;">"</span><span style="color: #800000;">Y-m-d H:i</span><span style="color: #800000;">"</span> }}&lt;/span&gt;&amp;nbsp;&amp;<span style="color: #000000;">nbsp;
                   </span>&lt;a href=<span style="color: #800000;">""</span>&gt;{{ comment.user.username }}&lt;/a&gt;
                   &lt;a href=<span style="color: #800000;">""</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">pull-right</span><span style="color: #800000;">"</span>&gt;&lt;span&gt;回复&lt;/span&gt;&lt;/a&gt;

               &lt;/div&gt;
               &lt;div&gt;
                   &lt;p&gt;{{ comment.content }}&lt;/p&gt;
               &lt;/div&gt;
            &lt;/li&gt;<span style="color: #000000;">
            {</span>% endfor %<span style="color: #000000;">}

        </span>&lt;/ul&gt;
        &lt;p&gt;发表评论&lt;/p&gt;
        &lt;p&gt;昵称:&lt;input type=<span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span> id=<span style="color: #800000;">"</span><span style="color: #800000;">tbCommentAuthor</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">author</span><span style="color: #800000;">"</span> disabled=<span style="color: #800000;">"</span><span style="color: #800000;">disabled</span><span style="color: #800000;">"</span> size=<span style="color: #800000;">"</span><span style="color: #800000;">50</span><span style="color: #800000;">"</span> value=<span style="color: #800000;">"</span><span style="color: #800000;">{{ request.user.username }}</span><span style="color: #800000;">"</span>&gt;&lt;/p&gt;
        &lt;div&gt;
            &lt;textarea name=<span style="color: #800000;">""</span> id=<span style="color: #800000;">"</span><span style="color: #800000;">comment_content</span><span style="color: #800000;">"</span> cols=<span style="color: #800000;">"</span><span style="color: #800000;">60</span><span style="color: #800000;">"</span> rows=<span style="color: #800000;">"</span><span style="color: #800000;">10</span><span style="color: #800000;">"</span>&gt;&lt;/textarea&gt;
        &lt;/div&gt;
        &lt;input type=<span style="color: #800000;">"</span><span style="color: #800000;">button</span><span style="color: #800000;">"</span> value=<span style="color: #800000;">"</span><span style="color: #800000;">submit</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">btn btn-default comment_btn</span><span style="color: #800000;">"</span>&gt;
    &lt;/div&gt;

&lt;/div&gt;<span style="color: #000000;">
{</span>% csrf_token %<span style="color: #000000;">}
</span>&lt;script&gt;<span style="color: #000000;">
    $(</span><span style="color: #800000;">"</span><span style="color: #800000;">.action</span><span style="color: #800000;">"</span><span style="color: #000000;">).click(function () {
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">hasClass() 方法检查被选元素是否包含指定的 class#}</span>
        var is_up = $(this).hasClass(<span style="color: #800000;">"</span><span style="color: #800000;">diggit</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">获取提示的span标签#}</span>
        var _this = $(this).children(<span style="color: #800000;">"</span><span style="color: #800000;">span</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">判断是否登录#}</span>
        <span style="color: #0000ff;">if</span> (<span style="color: #800000;">"</span><span style="color: #800000;">{{ request.user.username }}</span><span style="color: #800000;">"</span><span style="color: #000000;">) {
            $.ajax({
                url: </span><span style="color: #800000;">"</span><span style="color: #800000;">/digg/</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                type: </span><span style="color: #800000;">"</span><span style="color: #800000;">post</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                data: {
                    is_up: is_up,
                    article_id: </span><span style="color: #800000;">"</span><span style="color: #800000;">{{ article_obj.pk }}</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                    csrfmiddlewaretoken: $(</span><span style="color: #800000;">"</span><span style="color: #800000;">[name='csrfmiddlewaretoken']</span><span style="color: #800000;">"</span><span style="color: #000000;">).val()
                },
                success: function (data) {
                    console.log(data);
                    console.log(typeof data);
                    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (data.state) {
                        </span>//<span style="color: #000000;">提交成功
                        var val </span>= _this.text();  //<span style="color: #000000;">获取text值
                        </span>//<span style="color: #000000;">在原有的基础上加1。注意:一定要进行类型转换
                        _this.text(parseInt(val) </span>+ 1<span style="color: #000000;">)
                    } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
                        </span>//<span style="color: #000000;"> 重复提交
                        var val </span>= data.handled ? <span style="color: #800000;">"</span><span style="color: #800000;">您已经推荐过!</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">您已经反对过!</span><span style="color: #800000;">"</span><span style="color: #000000;">;
                        $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#digg_tips</span><span style="color: #800000;">"</span><span style="color: #000000;">).html(val);
                        setTimeout(function () {
                            $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#digg_tips</span><span style="color: #800000;">"</span>).html(<span style="color: #800000;">""</span>)  //<span style="color: #000000;">清空提示文字
                        }, </span>1000<span style="color: #000000;">)
                    }

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

修改css目录下的article_detail.css

注意放一个gif图片到img目录下

/*推荐和反对*/
#div_digg {
    float: right;
    margin-bottom: 10px;
    margin-right: 30px;
    font-size: 12px;
     125px;
    text-align: center;
    margin-top: 10px;
}

.diggit {
float: left;
46px;
height: 52px;
background: url("/static/img/upup.gif") no-repeat;
text
-align: center;
cursor: pointer;
margin
-top: 2px;
padding
-top: 5px;
}

.buryit {
float: right;
margin-left: 20px;
46px;
height: 52px;
background: url(
"/static/img/downdown.gif") no-repeat;
text
-align: center;
cursor: pointer;
margin
-top: 2px;
padding
-top: 5px;
}
.clear {
clear: both;
}

#digg_tips{
color: red;
}

/评论/
input.author{
background
-image: url("/static/img/icon_form.gif");
background
-repeat: no-repeat;
border: 1px solid
#ccc;
padding: 4px 4px 4px 30px;
300px;
font
-size: 13px;
}

input.author {
background-position: 3px -3px;
}

View Code

刷新网页,拉到最下面,效果如下:

评论步骤

  • 提交根评论请求
  • 显示根评论
  1. render
  2. Ajax显示
  • 提交子评论
  • 显示子评论
  • 评论树

发送ajax请求

查看评论表模型

class Comment(models.Model):
    """
评论表

</span><span style="color: #800000;">"""</span><span style="color: #000000;">
nid </span>= models.AutoField(primary_key=<span style="color: #000000;">True)
article </span>= models.ForeignKey(verbose_name=<span style="color: #800000;">'</span><span style="color: #800000;">评论文章</span><span style="color: #800000;">'</span>, to=<span style="color: #800000;">'</span><span style="color: #800000;">Article</span><span style="color: #800000;">'</span>, to_field=<span style="color: #800000;">'</span><span style="color: #800000;">nid</span><span style="color: #800000;">'</span>, on_delete=<span style="color: #000000;">models.CASCADE)
user </span>= models.ForeignKey(verbose_name=<span style="color: #800000;">'</span><span style="color: #800000;">评论者</span><span style="color: #800000;">'</span>, to=<span style="color: #800000;">'</span><span style="color: #800000;">UserInfo</span><span style="color: #800000;">'</span>, to_field=<span style="color: #800000;">'</span><span style="color: #800000;">nid</span><span style="color: #800000;">'</span>, on_delete=<span style="color: #000000;">models.CASCADE)
content </span>= models.CharField(verbose_name=<span style="color: #800000;">'</span><span style="color: #800000;">评论内容</span><span style="color: #800000;">'</span>, max_length=255<span style="color: #000000;">)
create_time </span>= models.DateTimeField(verbose_name=<span style="color: #800000;">'</span><span style="color: #800000;">创建时间</span><span style="color: #800000;">'</span>, auto_now_add=<span style="color: #000000;">True)
parent_comment </span>= models.ForeignKey(verbose_name=<span style="color: #800000;">"</span><span style="color: #800000;">父级评论id</span><span style="color: #800000;">"</span>, to=<span style="color: #800000;">'</span><span style="color: #800000;">Comment</span><span style="color: #800000;">'</span>,null=True, on_delete=models.CASCADE)</pre>
View Code

它有6个字段,其中nid、user、parent_comment、create_time是可选的。

user 在视图函数中,可以直接获取,不需要ajax传此参数。

parent_comment字段的值为空,表示这是一条根评论。否则为一条子评论!

那么ajax如果传一个空值,表示为根评论,否则为子评论。

create_time字段有一个属性:auto_now_add=True。

字段在实例第一次保存的时候会保存当前时间,不管你在这里是否对其赋值。但是之后的save()是可以手动赋值的。

也就是新实例化一个model,想手动存其他时间,就需要对该实例save()之后赋值然后再save()

根评论

修改article_detail.html的js代码,只需要发送3个参数即可。分别是content,atricle_id,parent_comment

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
<div class="clearfix"></div>

    &lt;div <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">comment</span><span style="color: #800000;">"</span>&gt;
        &lt;p&gt;评论列表&lt;/p&gt;
        &lt;ul <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">comment_list list-group</span><span style="color: #800000;">"</span>&gt;<span style="color: #000000;">
            {</span>% <span style="color: #0000ff;">for</span> comment <span style="color: #0000ff;">in</span> comment_list %<span style="color: #000000;">}
                </span>&lt;li <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">list-group-item</span><span style="color: #800000;">"</span>&gt;
                    &lt;div&gt;
                        &lt;a href=<span style="color: #800000;">""</span>&gt;<span style="color: #008000;">#</span><span style="color: #008000;">{{ forloop.counter }}楼&lt;/a&gt;&amp;nbsp;&amp;nbsp;</span>
                        &lt;span <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">small</span><span style="color: #800000;">"</span>&gt;{{ comment.create_time|date:<span style="color: #800000;">"</span><span style="color: #800000;">Y-m-d H:i</span><span style="color: #800000;">"</span> }}&lt;/span&gt;&amp;nbsp;&amp;<span style="color: #000000;">nbsp;
                        </span>&lt;a href=<span style="color: #800000;">""</span>&gt;{{ comment.user.username }}&lt;/a&gt;
                        &lt;a href=<span style="color: #800000;">""</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">pull-right</span><span style="color: #800000;">"</span>&gt;&lt;span&gt;回复&lt;/span&gt;&lt;/a&gt;

                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;p&gt;{{ comment.content }}&lt;/p&gt;
                    &lt;/div&gt;
                &lt;/li&gt;<span style="color: #000000;">
            {</span>% endfor %<span style="color: #000000;">}

        </span>&lt;/ul&gt;
        &lt;p&gt;发表评论&lt;/p&gt;
        &lt;p&gt;昵称:&lt;input type=<span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span> id=<span style="color: #800000;">"</span><span style="color: #800000;">tbCommentAuthor</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">author</span><span style="color: #800000;">"</span> disabled=<span style="color: #800000;">"</span><span style="color: #800000;">disabled</span><span style="color: #800000;">"</span> size=<span style="color: #800000;">"</span><span style="color: #800000;">50</span><span style="color: #800000;">"</span><span style="color: #000000;">
                     value</span>=<span style="color: #800000;">"</span><span style="color: #800000;">{{ request.user.username }}</span><span style="color: #800000;">"</span>&gt;&lt;/p&gt;
        &lt;div&gt;
            &lt;textarea name=<span style="color: #800000;">""</span> id=<span style="color: #800000;">"</span><span style="color: #800000;">comment_content</span><span style="color: #800000;">"</span> cols=<span style="color: #800000;">"</span><span style="color: #800000;">60</span><span style="color: #800000;">"</span> rows=<span style="color: #800000;">"</span><span style="color: #800000;">10</span><span style="color: #800000;">"</span>&gt;&lt;/textarea&gt;
        &lt;/div&gt;
        &lt;input type=<span style="color: #800000;">"</span><span style="color: #800000;">button</span><span style="color: #800000;">"</span> value=<span style="color: #800000;">"</span><span style="color: #800000;">submit</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">btn btn-default comment_btn</span><span style="color: #800000;">"</span>&gt;
    &lt;/div&gt;

&lt;/div&gt;<span style="color: #000000;">
{</span>% csrf_token %<span style="color: #000000;">}
</span>&lt;script&gt;
    //<span style="color: #000000;"> 点赞和踩灭
    $(</span><span style="color: #800000;">"</span><span style="color: #800000;">.action</span><span style="color: #800000;">"</span><span style="color: #000000;">).click(function () {
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">hasClass() 方法检查被选元素是否包含指定的 class#}</span>
        var is_up = $(this).hasClass(<span style="color: #800000;">"</span><span style="color: #800000;">diggit</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">获取提示的span标签#}</span>
        var _this = $(this).children(<span style="color: #800000;">"</span><span style="color: #800000;">span</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">判断是否登录#}</span>
        <span style="color: #0000ff;">if</span> (<span style="color: #800000;">"</span><span style="color: #800000;">{{ request.user.username }}</span><span style="color: #800000;">"</span><span style="color: #000000;">) {
            $.ajax({
                url: </span><span style="color: #800000;">"</span><span style="color: #800000;">/digg/</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                type: </span><span style="color: #800000;">"</span><span style="color: #800000;">post</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                data: {
                    is_up: is_up,
                    article_id: </span><span style="color: #800000;">"</span><span style="color: #800000;">{{ article_obj.pk }}</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                    csrfmiddlewaretoken: $(</span><span style="color: #800000;">"</span><span style="color: #800000;">[name='csrfmiddlewaretoken']</span><span style="color: #800000;">"</span><span style="color: #000000;">).val()
                },
                success: function (data) {
                    console.log(data);
                    console.log(typeof data);
                    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (data.state) {
                        </span>//<span style="color: #000000;">提交成功
                        var val </span>= _this.text();  //<span style="color: #000000;">获取text值
                        </span>//<span style="color: #000000;">在原有的基础上加1。注意:一定要进行类型转换
                        _this.text(parseInt(val) </span>+ 1<span style="color: #000000;">)
                    } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
                        </span>//<span style="color: #000000;"> 重复提交
                        var val </span>= data.handled ? <span style="color: #800000;">"</span><span style="color: #800000;">您已经推荐过!</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">您已经反对过!</span><span style="color: #800000;">"</span><span style="color: #000000;">;
                        $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#digg_tips</span><span style="color: #800000;">"</span><span style="color: #000000;">).html(val);
                        setTimeout(function () {
                            $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#digg_tips</span><span style="color: #800000;">"</span>).html(<span style="color: #800000;">""</span>)  //<span style="color: #000000;">清空提示文字
                        }, </span>1000<span style="color: #000000;">)
                    }

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })

    </span>//<span style="color: #000000;"> 提交评论
    $(</span><span style="color: #800000;">"</span><span style="color: #800000;">.comment_btn</span><span style="color: #800000;">"</span><span style="color: #000000;">).click(function () {
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">评论内容#}</span>
        var content = $(<span style="color: #800000;">"</span><span style="color: #800000;">#comment_content</span><span style="color: #800000;">"</span><span style="color: #000000;">).val();
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">默认为空#}</span>
        var pid = <span style="color: #800000;">""</span><span style="color: #000000;">;
        $.ajax({
            url: </span><span style="color: #800000;">"</span><span style="color: #800000;">/comment/</span><span style="color: #800000;">"</span><span style="color: #000000;">,
            type: </span><span style="color: #800000;">"</span><span style="color: #800000;">post</span><span style="color: #800000;">"</span><span style="color: #000000;">,
            data: {
                content: content,
                article_id: </span><span style="color: #800000;">"</span><span style="color: #800000;">{{ article_obj.pk }}</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                pid: pid,
                csrfmiddlewaretoken: $(</span><span style="color: #800000;">"</span><span style="color: #800000;">[name='csrfmiddlewaretoken']</span><span style="color: #800000;">"</span><span style="color: #000000;">).val()
            },
            success: function (data) {
                console.log(data);
                </span>//<span style="color: #000000;"> 清空输入框的内容
                $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#comment_content</span><span style="color: #800000;">"</span>).val(<span style="color: #800000;">""</span><span style="color: #000000;">)
            }
        })

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

修改urls.py,增加路径comment

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    path('', views.index),
    #点赞或者踩灭
    path('digg/', views.digg),
    # 评论
    path('comment/', views.comment),
</span><span style="color: #008000;">#</span><span style="color: #008000;">文章详情</span>
re_path(<span style="color: #800000;">'</span><span style="color: #800000;">(?P&lt;username&gt;w+)/articles/(?P&lt;article_id&gt;d+)/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, views.article_detail),
</span><span style="color: #008000;">#</span><span style="color: #008000;"> 跳转</span>
re_path(<span style="color: #800000;">'</span><span style="color: #800000;">(?P&lt;username&gt;w+)/(?P&lt;condition&gt;category|tag|achrive)/(?P&lt;params&gt;.*)/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, views.homesite),
</span><span style="color: #008000;">#</span><span style="color: #008000;"> 个人站点</span>
re_path(<span style="color: #800000;">'</span><span style="color: #800000;">(?P&lt;username&gt;w+)/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, views.homesite),

]

View Code

修改views.py,增加视图函数comment,完整代码如下:

from django.shortcuts import render,HttpResponse,redirect
from django.contrib import auth
from blog.models import Article,UserInfo,Blog,Category,Tag,ArticleUpDown,Comment
from django.db.models import Sum,Avg,Max,Min,Count
from django.db.models import F
import json
from django.http import JsonResponse
from django.db import transaction

# Create your views here.
def login(request):

</span><span style="color: #0000ff;">if</span> request.method==<span style="color: #800000;">"</span><span style="color: #800000;">POST</span><span style="color: #800000;">"</span><span style="color: #000000;">:
    user</span>=request.POST.get(<span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    pwd</span>=request.POST.get(<span style="color: #800000;">"</span><span style="color: #800000;">pwd</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> 用户验证成功,返回user对象,否则返回None</span>
    user=auth.authenticate(username=user,password=<span style="color: #000000;">pwd)
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> user:
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> 登录,注册session</span>
        <span style="color: #008000;">#</span><span style="color: #008000;"> 全局变量 request.user=当前登陆对象(session中)</span>

auth.login(request,user)
return redirect("/index/")

</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">"</span><span style="color: #800000;">login.html</span><span style="color: #800000;">"</span><span style="color: #000000;">)

def index(request):
article_list
=Article.objects.all()
return render(request,"index.html",{"article_list":article_list})

def logout(request): # 注销
auth.logout(request)
return redirect("/index/")

def query_current_site(request,username): # 查询当前站点的博客标题
# 查询当前站点的用户对象
user = UserInfo.objects.filter(username=username).first()
if not user:
return render(request, "not_found.html")
# 查询当前站点对象
blog = user.blog
return blog

def homesite(request,username,**kwargs): # 个人站点主页
print("kwargs", kwargs)

blog </span>=<span style="color: #000000;"> query_current_site(request,username)

</span><span style="color: #008000;">#</span><span style="color: #008000;"> 查询当前用户发布的所有文章</span>
<span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span><span style="color: #000000;"> kwargs:
    article_list </span>= Article.objects.filter(user__username=<span style="color: #000000;">username)
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    condition </span>= kwargs.get(<span style="color: #800000;">"</span><span style="color: #800000;">condition</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    params </span>= kwargs.get(<span style="color: #800000;">"</span><span style="color: #800000;">params</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    </span><span style="color: #008000;">#</span><span style="color: #008000;">判断分类、随笔、归档</span>
    <span style="color: #0000ff;">if</span> condition == <span style="color: #800000;">"</span><span style="color: #800000;">category</span><span style="color: #800000;">"</span><span style="color: #000000;">:
        article_list </span>= Article.objects.filter(user__username=username).filter(category__title=<span style="color: #000000;">params)
    </span><span style="color: #0000ff;">elif</span> condition == <span style="color: #800000;">"</span><span style="color: #800000;">tag</span><span style="color: #800000;">"</span><span style="color: #000000;">:
        article_list </span>= Article.objects.filter(user__username=username).filter(tags__title=<span style="color: #000000;">params)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        year, month </span>= params.split(<span style="color: #800000;">"</span><span style="color: #800000;">/</span><span style="color: #800000;">"</span><span style="color: #000000;">)
        article_list </span>= Article.objects.filter(user__username=username).filter(create_time__year=<span style="color: #000000;">year,
                                                                              create_time__month</span>=<span style="color: #000000;">month)
</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">"</span><span style="color: #800000;">homesite.html</span><span style="color: #800000;">"</span>,{<span style="color: #800000;">"</span><span style="color: #800000;">blog</span><span style="color: #800000;">"</span>:blog,<span style="color: #800000;">"</span><span style="color: #800000;">username</span><span style="color: #800000;">"</span>:username,<span style="color: #800000;">"</span><span style="color: #800000;">article_list</span><span style="color: #800000;">"</span><span style="color: #000000;">:article_list})

def article_detail(request,username,article_id):
blog
= query_current_site(request,username)

</span><span style="color: #008000;">#</span><span style="color: #008000;">查询指定id的文章</span>
article_obj = Article.objects.filter(pk=<span style="color: #000000;">article_id).first()
user_id </span>= UserInfo.objects.filter(username=<span style="color: #000000;">username).first().nid

</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">'</span><span style="color: #800000;">article_detail.html</span><span style="color: #800000;">'</span>,{<span style="color: #800000;">"</span><span style="color: #800000;">blog</span><span style="color: #800000;">"</span>:blog,<span style="color: #800000;">"</span><span style="color: #800000;">username</span><span style="color: #800000;">"</span>:username,<span style="color: #800000;">'</span><span style="color: #800000;">article_obj</span><span style="color: #800000;">'</span>:article_obj,<span style="color: #800000;">"</span><span style="color: #800000;">user_id</span><span style="color: #800000;">"</span><span style="color: #000000;">:user_id})

def digg(request):
print(request.POST)
if request.method == "POST":
#ajax发送的过来的true和false是字符串,使用json反序列化得到布尔值
is_up = json.loads(request.POST.get("is_up"))
article_id
= request.POST.get("article_id")
user_id
= request.user.pk

    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: True, <span style="color: #800000;">"</span><span style="color: #800000;">msg</span><span style="color: #800000;">"</span>: None}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">判断当前登录用户是否对这篇文章做过点赞或者踩灭操作</span>
    obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=<span style="color: #000000;">article_id).first()
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> obj:
        response[</span><span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>] = False  <span style="color: #008000;">#</span><span style="color: #008000;"> 更改状态</span>
        response[<span style="color: #800000;">"</span><span style="color: #800000;">handled</span><span style="color: #800000;">"</span>] = obj.is_up  <span style="color: #008000;">#</span><span style="color: #008000;"> 获取之前的操作,返回true或者false</span>
        <span style="color: #0000ff;">print</span><span style="color: #000000;">(obj.is_up)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        with transaction.atomic():
            </span><span style="color: #008000;">#</span><span style="color: #008000;">插入一条记录</span>
            new_obj = ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=<span style="color: #000000;">is_up)
            </span><span style="color: #0000ff;">if</span> is_up: <span style="color: #008000;">#</span><span style="color: #008000;"> 判断为推荐</span>
                Article.objects.filter(pk=article_id).update(up_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">up_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)
            </span><span style="color: #0000ff;">else</span>: <span style="color: #008000;">#</span><span style="color: #008000;"> 反对</span>
                Article.objects.filter(pk=article_id).update(down_count=F(<span style="color: #800000;">"</span><span style="color: #800000;">down_count</span><span style="color: #800000;">"</span>)+1<span style="color: #000000;">)

    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> JsonResponse(response)

</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span><span style="color: #000000;">)

def comment(request):
print(request.POST)
if request.method == "POST":
# 获取数据
user_id = request.user.pk
article_id
= request.POST.get("article_id")
content
= request.POST.get("content")
pid
= request.POST.get("pid")
# 生成评论对象
with transaction.atomic(): # 增加事务
# 评论表增加一条记录
comment = Comment.objects.create(user_id=user_id, article_id=article_id, content=content, parent_comment_id=pid)
# 当前文章的评论数加1
Article.objects.filter(pk=article_id).update(comment_count=F("comment_count") + 1)

    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: False}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>
    
    <span style="color: #0000ff;">if</span> comment.user_id:  <span style="color: #008000;">#</span><span style="color: #008000;"> 判断返回值</span>
        response = {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span><span style="color: #000000;">: True}
    
    </span><span style="color: #0000ff;">return</span> JsonResponse(response)  <span style="color: #008000;">#</span><span style="color: #008000;"> 返回json对象</span>

<span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span>)</pre>
View Code

刷新网页,发表一条评论

 查看表blog_comment,多了一条记录

查看blog_article表,对应的comment_count值,数值加1了。

 

渲染评论

修改article_detail视图函数,将评论列表传给模板

def article_detail(request,username,article_id):
    blog = query_current_site(request,username)
</span><span style="color: #008000;">#</span><span style="color: #008000;">查询指定id的文章</span>
article_obj = Article.objects.filter(pk=<span style="color: #000000;">article_id).first()
user_id </span>= UserInfo.objects.filter(username=<span style="color: #000000;">username).first().nid

comment_list </span>= Comment.objects.filter(article_id=<span style="color: #000000;">article_id)
dict </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">blog</span><span style="color: #800000;">"</span><span style="color: #000000;">:blog,
        </span><span style="color: #800000;">"</span><span style="color: #800000;">username</span><span style="color: #800000;">"</span><span style="color: #000000;">:username,
        </span><span style="color: #800000;">'</span><span style="color: #800000;">article_obj</span><span style="color: #800000;">'</span><span style="color: #000000;">:article_obj,
        </span><span style="color: #800000;">"</span><span style="color: #800000;">user_id</span><span style="color: #800000;">"</span><span style="color: #000000;">:user_id,
        </span><span style="color: #800000;">"</span><span style="color: #800000;">comment_list</span><span style="color: #800000;">"</span><span style="color: #000000;">:comment_list,
        }

</span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">'</span><span style="color: #800000;">article_detail.html</span><span style="color: #800000;">'</span>,dict)</pre>
View Code

修改article_detail.html,使用for循环,遍历列表

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
<div class="clearfix"></div>

    &lt;div <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">comment</span><span style="color: #800000;">"</span>&gt;
        &lt;p&gt;评论列表&lt;/p&gt;
        &lt;ul <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">comment_list list-group</span><span style="color: #800000;">"</span>&gt;<span style="color: #000000;">
            {</span>% <span style="color: #0000ff;">for</span> comment <span style="color: #0000ff;">in</span> comment_list %<span style="color: #000000;">}
                </span>&lt;li <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">list-group-item</span><span style="color: #800000;">"</span>&gt;
                    &lt;div&gt;
                        &lt;a href=<span style="color: #800000;">""</span>&gt;<span style="color: #008000;">#</span><span style="color: #008000;">{{ forloop.counter }}楼&lt;/a&gt;&amp;nbsp;&amp;nbsp;</span>
                        &lt;span <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">small</span><span style="color: #800000;">"</span>&gt;{{ comment.create_time|date:<span style="color: #800000;">"</span><span style="color: #800000;">Y-m-d H:i</span><span style="color: #800000;">"</span> }}&lt;/span&gt;&amp;nbsp;&amp;<span style="color: #000000;">nbsp;
                        </span>&lt;a href=<span style="color: #800000;">""</span>&gt;{{ comment.user.username }}&lt;/a&gt;
                        &lt;a href=<span style="color: #800000;">""</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">pull-right</span><span style="color: #800000;">"</span>&gt;&lt;span&gt;回复&lt;/span&gt;&lt;/a&gt;

                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;p&gt;{{ comment.content }}&lt;/p&gt;
                    &lt;/div&gt;
                &lt;/li&gt;<span style="color: #000000;">
            {</span>% endfor %<span style="color: #000000;">}

        </span>&lt;/ul&gt;
        &lt;p&gt;发表评论&lt;/p&gt;
        &lt;p&gt;昵称:&lt;input type=<span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span> id=<span style="color: #800000;">"</span><span style="color: #800000;">tbCommentAuthor</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">author</span><span style="color: #800000;">"</span> disabled=<span style="color: #800000;">"</span><span style="color: #800000;">disabled</span><span style="color: #800000;">"</span> size=<span style="color: #800000;">"</span><span style="color: #800000;">50</span><span style="color: #800000;">"</span><span style="color: #000000;">
                     value</span>=<span style="color: #800000;">"</span><span style="color: #800000;">{{ request.user.username }}</span><span style="color: #800000;">"</span>&gt;&lt;/p&gt;
        &lt;div&gt;
            &lt;textarea name=<span style="color: #800000;">""</span> id=<span style="color: #800000;">"</span><span style="color: #800000;">comment_content</span><span style="color: #800000;">"</span> cols=<span style="color: #800000;">"</span><span style="color: #800000;">60</span><span style="color: #800000;">"</span> rows=<span style="color: #800000;">"</span><span style="color: #800000;">10</span><span style="color: #800000;">"</span>&gt;&lt;/textarea&gt;
        &lt;/div&gt;
        &lt;input type=<span style="color: #800000;">"</span><span style="color: #800000;">button</span><span style="color: #800000;">"</span> value=<span style="color: #800000;">"</span><span style="color: #800000;">submit</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">btn btn-default comment_btn</span><span style="color: #800000;">"</span>&gt;
    &lt;/div&gt;

&lt;/div&gt;<span style="color: #000000;">
{</span>% csrf_token %<span style="color: #000000;">}
</span>&lt;script&gt;
    //<span style="color: #000000;"> 点赞和踩灭
    $(</span><span style="color: #800000;">"</span><span style="color: #800000;">.action</span><span style="color: #800000;">"</span><span style="color: #000000;">).click(function () {
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">hasClass() 方法检查被选元素是否包含指定的 class#}</span>
        var is_up = $(this).hasClass(<span style="color: #800000;">"</span><span style="color: #800000;">diggit</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">获取提示的span标签#}</span>
        var _this = $(this).children(<span style="color: #800000;">"</span><span style="color: #800000;">span</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">判断是否登录#}</span>
        <span style="color: #0000ff;">if</span> (<span style="color: #800000;">"</span><span style="color: #800000;">{{ request.user.username }}</span><span style="color: #800000;">"</span><span style="color: #000000;">) {
            $.ajax({
                url: </span><span style="color: #800000;">"</span><span style="color: #800000;">/digg/</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                type: </span><span style="color: #800000;">"</span><span style="color: #800000;">post</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                data: {
                    is_up: is_up,
                    article_id: </span><span style="color: #800000;">"</span><span style="color: #800000;">{{ article_obj.pk }}</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                    csrfmiddlewaretoken: $(</span><span style="color: #800000;">"</span><span style="color: #800000;">[name='csrfmiddlewaretoken']</span><span style="color: #800000;">"</span><span style="color: #000000;">).val()
                },
                success: function (data) {
                    console.log(data);
                    console.log(typeof data);
                    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (data.state) {
                        </span>//<span style="color: #000000;">提交成功
                        var val </span>= _this.text();  //<span style="color: #000000;">获取text值
                        </span>//<span style="color: #000000;">在原有的基础上加1。注意:一定要进行类型转换
                        _this.text(parseInt(val) </span>+ 1<span style="color: #000000;">)
                    } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
                        </span>//<span style="color: #000000;"> 重复提交
                        var val </span>= data.handled ? <span style="color: #800000;">"</span><span style="color: #800000;">您已经推荐过!</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">您已经反对过!</span><span style="color: #800000;">"</span><span style="color: #000000;">;
                        $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#digg_tips</span><span style="color: #800000;">"</span><span style="color: #000000;">).html(val);
                        setTimeout(function () {
                            $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#digg_tips</span><span style="color: #800000;">"</span>).html(<span style="color: #800000;">""</span>)  //<span style="color: #000000;">清空提示文字
                        }, </span>1000<span style="color: #000000;">)
                    }

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })

    </span>//<span style="color: #000000;"> 提交评论
    $(</span><span style="color: #800000;">"</span><span style="color: #800000;">.comment_btn</span><span style="color: #800000;">"</span><span style="color: #000000;">).click(function () {
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">评论内容#}</span>
        var content = $(<span style="color: #800000;">"</span><span style="color: #800000;">#comment_content</span><span style="color: #800000;">"</span><span style="color: #000000;">).val();
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">默认为空#}</span>
        var pid = <span style="color: #800000;">""</span><span style="color: #000000;">;
        $.ajax({
            url: </span><span style="color: #800000;">"</span><span style="color: #800000;">/comment/</span><span style="color: #800000;">"</span><span style="color: #000000;">,
            type: </span><span style="color: #800000;">"</span><span style="color: #800000;">post</span><span style="color: #800000;">"</span><span style="color: #000000;">,
            data: {
                content: content,
                article_id: </span><span style="color: #800000;">"</span><span style="color: #800000;">{{ article_obj.pk }}</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                pid: pid,
                csrfmiddlewaretoken: $(</span><span style="color: #800000;">"</span><span style="color: #800000;">[name='csrfmiddlewaretoken']</span><span style="color: #800000;">"</span><span style="color: #000000;">).val()
            },
            success: function (data) {
                console.log(data);
                </span>//<span style="color: #000000;"> 清空输入框的内容
                $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#comment_content</span><span style="color: #800000;">"</span>).val(<span style="color: #800000;">""</span><span style="color: #000000;">)
            }
        })

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

刷新网页,效果如下:

评论实时展示

上面提交评论后,网页不能立即看到,需要刷新之后,才能看到。这样体验不好!

查看博客园的评论,提交之后,会立即看到评论。此时不会显示楼层,只会显示评论内容!

那么只需要提交成功之后,操作DOM,在评论列表中,追加一段li标签,展示一下,就可以了!

数据获取问题

那么内容从何而来呢?

1.直接从html中获取相关数据

2.让服务器返回相关数据,从响应体中取数据。

针对这2种方式,我们选择第2种!

为什么不选择第一种呢?因为第一种是原始输入框中的值,那么存储到数据后之后。就不一定还是输入框的值!

服务器存储到数据库之前,会将提交的数据,做一次处理!

我们想要的效果,就是不论是DOM操作,追加一段html代码。还是刷新网页,加载评论。这2种方式,评论内容是一摸一样的!

所以,我们必须选择第二种方案,让服务器返回存储的值给ajax,ajax操作DOM,最加一段html代码,给用户展示!

数据展示

修改comment视图函数,返回3个变量给ajax

def comment(request):
    print(request.POST)
    if request.method == "POST":
        # 获取数据
        user_id = request.user.pk
        article_id = request.POST.get("article_id")
        content = request.POST.get("content")
        pid = request.POST.get("pid")
        # 生成评论对象
        with transaction.atomic():  # 增加事务
            # 评论表增加一条记录
            comment = Comment.objects.create(user_id=user_id, article_id=article_id, content=content, parent_comment_id=pid)
            # 当前文章的评论数加1
            Article.objects.filter(pk=article_id).update(comment_count=F("comment_count") + 1)
    response </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span>: False}  <span style="color: #008000;">#</span><span style="color: #008000;"> 初始状态</span>

    <span style="color: #0000ff;">if</span> comment.user_id:  <span style="color: #008000;">#</span><span style="color: #008000;"> 判断返回值</span>
        response = {<span style="color: #800000;">"</span><span style="color: #800000;">state</span><span style="color: #800000;">"</span><span style="color: #000000;">: True}
    
    </span><span style="color: #008000;">#</span><span style="color: #008000;">响应体增加3个变量</span>
    response[<span style="color: #800000;">"</span><span style="color: #800000;">timer</span><span style="color: #800000;">"</span>] = comment.create_time.strftime(<span style="color: #800000;">"</span><span style="color: #800000;">%Y-%m-%d %X</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    response[</span><span style="color: #800000;">"</span><span style="color: #800000;">content</span><span style="color: #800000;">"</span>] =<span style="color: #000000;"> comment.content
    response[</span><span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span>] =<span style="color: #000000;"> request.user.username
    
    </span><span style="color: #0000ff;">return</span> JsonResponse(response)  <span style="color: #008000;">#</span><span style="color: #008000;"> 返回json对象</span>

<span style="color: #0000ff;">else</span><span style="color: #000000;">:
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">非法请求</span><span style="color: #800000;">"</span>)</pre>
View Code

修改article_detail.html中的js代码,使用append最加一段li标签

{% extends "base.html" %}

{% block content %}
<div class="article_info">
<h4 class="text-center">{{ article_obj.title }}</h4>
<div class="content">
{{ article_obj.content
|safe }}
</div>
<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips">
</div>
</div>
<div class="clearfix"></div>

    &lt;div <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">comment</span><span style="color: #800000;">"</span>&gt;
        &lt;p&gt;评论列表&lt;/p&gt;
        &lt;ul <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">comment_list list-group</span><span style="color: #800000;">"</span>&gt;<span style="color: #000000;">
            {</span>% <span style="color: #0000ff;">for</span> comment <span style="color: #0000ff;">in</span> comment_list %<span style="color: #000000;">}
                </span>&lt;li <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">list-group-item</span><span style="color: #800000;">"</span>&gt;
                    &lt;div&gt;
                        &lt;a href=<span style="color: #800000;">""</span>&gt;<span style="color: #008000;">#</span><span style="color: #008000;">{{ forloop.counter }}楼&lt;/a&gt;&amp;nbsp;&amp;nbsp;</span>
                        &lt;span <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">small</span><span style="color: #800000;">"</span>&gt;{{ comment.create_time|date:<span style="color: #800000;">"</span><span style="color: #800000;">Y-m-d H:i</span><span style="color: #800000;">"</span> }}&lt;/span&gt;&amp;nbsp;&amp;<span style="color: #000000;">nbsp;
                        </span>&lt;a href=<span style="color: #800000;">""</span>&gt;{{ comment.user.username }}&lt;/a&gt;
                        &lt;a href=<span style="color: #800000;">""</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">pull-right</span><span style="color: #800000;">"</span>&gt;&lt;span&gt;回复&lt;/span&gt;&lt;/a&gt;

                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;p&gt;{{ comment.content }}&lt;/p&gt;
                    &lt;/div&gt;
                &lt;/li&gt;<span style="color: #000000;">
            {</span>% endfor %<span style="color: #000000;">}

        </span>&lt;/ul&gt;
        &lt;p&gt;发表评论&lt;/p&gt;
        &lt;p&gt;昵称:&lt;input type=<span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span> id=<span style="color: #800000;">"</span><span style="color: #800000;">tbCommentAuthor</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">author</span><span style="color: #800000;">"</span> disabled=<span style="color: #800000;">"</span><span style="color: #800000;">disabled</span><span style="color: #800000;">"</span> size=<span style="color: #800000;">"</span><span style="color: #800000;">50</span><span style="color: #800000;">"</span><span style="color: #000000;">
                     value</span>=<span style="color: #800000;">"</span><span style="color: #800000;">{{ request.user.username }}</span><span style="color: #800000;">"</span>&gt;&lt;/p&gt;
        &lt;div&gt;
            &lt;textarea name=<span style="color: #800000;">""</span> id=<span style="color: #800000;">"</span><span style="color: #800000;">comment_content</span><span style="color: #800000;">"</span> cols=<span style="color: #800000;">"</span><span style="color: #800000;">60</span><span style="color: #800000;">"</span> rows=<span style="color: #800000;">"</span><span style="color: #800000;">10</span><span style="color: #800000;">"</span>&gt;&lt;/textarea&gt;
        &lt;/div&gt;
        &lt;input type=<span style="color: #800000;">"</span><span style="color: #800000;">button</span><span style="color: #800000;">"</span> value=<span style="color: #800000;">"</span><span style="color: #800000;">submit</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">btn btn-default comment_btn</span><span style="color: #800000;">"</span>&gt;
    &lt;/div&gt;

&lt;/div&gt;<span style="color: #000000;">
{</span>% csrf_token %<span style="color: #000000;">}
</span>&lt;script&gt;
    //<span style="color: #000000;"> 点赞和踩灭
    $(</span><span style="color: #800000;">"</span><span style="color: #800000;">.action</span><span style="color: #800000;">"</span><span style="color: #000000;">).click(function () {
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">hasClass() 方法检查被选元素是否包含指定的 class#}</span>
        var is_up = $(this).hasClass(<span style="color: #800000;">"</span><span style="color: #800000;">diggit</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">获取提示的span标签#}</span>
        var _this = $(this).children(<span style="color: #800000;">"</span><span style="color: #800000;">span</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">判断是否登录#}</span>
        <span style="color: #0000ff;">if</span> (<span style="color: #800000;">"</span><span style="color: #800000;">{{ request.user.username }}</span><span style="color: #800000;">"</span><span style="color: #000000;">) {
            $.ajax({
                url: </span><span style="color: #800000;">"</span><span style="color: #800000;">/digg/</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                type: </span><span style="color: #800000;">"</span><span style="color: #800000;">post</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                data: {
                    is_up: is_up,
                    article_id: </span><span style="color: #800000;">"</span><span style="color: #800000;">{{ article_obj.pk }}</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                    csrfmiddlewaretoken: $(</span><span style="color: #800000;">"</span><span style="color: #800000;">[name='csrfmiddlewaretoken']</span><span style="color: #800000;">"</span><span style="color: #000000;">).val()
                },
                success: function (data) {
                    console.log(data);
                    console.log(typeof data);
                    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (data.state) {
                        </span>//<span style="color: #000000;">提交成功
                        var val </span>= _this.text();  //<span style="color: #000000;">获取text值
                        </span>//<span style="color: #000000;">在原有的基础上加1。注意:一定要进行类型转换
                        _this.text(parseInt(val) </span>+ 1<span style="color: #000000;">)
                    } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
                        </span>//<span style="color: #000000;"> 重复提交
                        var val </span>= data.handled ? <span style="color: #800000;">"</span><span style="color: #800000;">您已经推荐过!</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">您已经反对过!</span><span style="color: #800000;">"</span><span style="color: #000000;">;
                        $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#digg_tips</span><span style="color: #800000;">"</span><span style="color: #000000;">).html(val);
                        setTimeout(function () {
                            $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#digg_tips</span><span style="color: #800000;">"</span>).html(<span style="color: #800000;">""</span>)  //<span style="color: #000000;">清空提示文字
                        }, </span>1000<span style="color: #000000;">)
                    }

                }
            })
        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
            location.href </span>= <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">;
        }

    })

    </span>//<span style="color: #000000;"> 提交评论
    $(</span><span style="color: #800000;">"</span><span style="color: #800000;">.comment_btn</span><span style="color: #800000;">"</span><span style="color: #000000;">).click(function () {
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">评论内容#}</span>
        var content = $(<span style="color: #800000;">"</span><span style="color: #800000;">#comment_content</span><span style="color: #800000;">"</span><span style="color: #000000;">).val();
        {</span><span style="color: #008000;">#</span><span style="color: #008000;">默认为空#}</span>
        var pid = <span style="color: #800000;">""</span><span style="color: #000000;">;
        $.ajax({
            url: </span><span style="color: #800000;">"</span><span style="color: #800000;">/comment/</span><span style="color: #800000;">"</span><span style="color: #000000;">,
            type: </span><span style="color: #800000;">"</span><span style="color: #800000;">post</span><span style="color: #800000;">"</span><span style="color: #000000;">,
            data: {
                content: content,
                article_id: </span><span style="color: #800000;">"</span><span style="color: #800000;">{{ article_obj.pk }}</span><span style="color: #800000;">"</span><span style="color: #000000;">,
                pid: pid,
                csrfmiddlewaretoken: $(</span><span style="color: #800000;">"</span><span style="color: #800000;">[name='csrfmiddlewaretoken']</span><span style="color: #800000;">"</span><span style="color: #000000;">).val()
            },
            success: function (data) {
                console.log(data);
                {</span><span style="color: #008000;">#</span><span style="color: #008000;">获取3个值#}</span>
                var comment_time =<span style="color: #000000;"> data.timer;
                var comment_content </span>=<span style="color: #000000;"> data.content;
                var comment_user </span>=<span style="color: #000000;"> data.user;
                {</span><span style="color: #008000;">#</span><span style="color: #008000;">组织li标签#}</span>
                var $li = ` &lt;li <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">list-group-item</span><span style="color: #800000;">"</span>&gt;
                                   &lt;div&gt;
                                       &lt;span <span style="color: #0000ff;">class</span>=<span style="color: #800000;">"</span><span style="color: #800000;">small</span><span style="color: #800000;">"</span>&gt;${comment_time}&lt;/span&gt;&amp;nbsp;&amp;<span style="color: #000000;">nbsp;
                                       </span>&lt;a href=<span style="color: #800000;">""</span>&gt;${comment_user}&lt;/a&gt;
                                   &lt;/div&gt;
                                   &lt;div&gt;
                                       &lt;p&gt;${comment_content}&lt;/p&gt;
                                   &lt;/div&gt;
                                &lt;/li&gt;<span style="color: #000000;">`;
                {</span><span style="color: #008000;">#</span><span style="color: #008000;">追加到评论列表中#}</span>
                $(<span style="color: #800000;">"</span><span style="color: #800000;">.comment_list</span><span style="color: #800000;">"</span><span style="color: #000000;">).append($li);
                </span>//<span style="color: #000000;"> 清空输入框的内容
                $(</span><span style="color: #800000;">"</span><span style="color: #800000;">#comment_content</span><span style="color: #800000;">"</span>).val(<span style="color: #800000;">""</span><span style="color: #000000;">)
            }
        })

    })
</span>&lt;/script&gt;<span style="color: #000000;">

{% endblock %}

View Code

刷新网页,重新评论,效果如下:

评论可以实时展示了

刷新网页,效果如下:

显示出楼层


参考资料:

Django 基础教程

转载声明:
作者:肖祥
出处: https://www.cnblogs.com/xiao987334176/

原文地址:https://www.cnblogs.com/bqwzx/p/10198770.html