zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    SM3国密算法标准中两个实例的实现
    2017-2018《网络攻防技术》第十周作业
    2017-2018《网络攻防技术》第九周作业
    2017-2018网络攻防技术第八周作业
    第十一周作业
    指针学习
    2017-2018第七周网络攻防作业
    2017-2018网络攻防第六周作业
    2017-2018网络攻防第五周作业
    spark要我命_2_算了,不起标题了
  • 原文地址:https://www.cnblogs.com/bqwzx/p/10198770.html
Copyright © 2011-2022 走看看