• 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/

  • 相关阅读:
    DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践
    UVA10071 Back to High School Physics
    UVA10071 Back to High School Physics
    UVA10055 Hashmat the Brave Warrior
    UVA10055 Hashmat the Brave Warrior
    UVA458 The Decoder
    UVA458 The Decoder
    HDU2054 A == B ?
    HDU2054 A == B ?
    POJ3414 Pots
  • 原文地址:https://www.cnblogs.com/bqwzx/p/10198770.html
Copyright © 2020-2023  润新知