一、路由
from django. contrib import admin
from django. urls import path, re_path
from app01 import views
from django. views. static import serve
from django. conf import settingsurlpatterns = [ path( 'admin/' , admin. site. urls) , path( 'register/' , views. register) , path( 'login/' , views. login) , path( 'get_code/' , views. get_code) , path( 'home/' , views. home) , path( 'logout/' , views. logout) , path( 'set_password/' , views. set_password) , re_path( 'media/(?P<path>.*)' , serve, { 'document_root' : settings. MEDIA_ROOT} ) , path( 'up_and_down/' , views. up_and_down) , path( 'comment/' , views. comment) , re_path( '(?P<username>\w+)/(?P<condition>category|tag|archive)/(?P<param>.*)' , views. site) , re_path( '(?P<username>\w+)/(?P<article_id>\d+)' , views. article_detail) , re_path( '(?P<username>\w+)' , views. site) ,
]
二、文章详情页
1.前端
{% extends 'home.html' %}{% block css %}< style> .s1 { margin-right : 10px; color : #999; } .content { font-size : 18px; color : #444; } #div_digg { float : right; margin-bottom : 10px; margin-right : 30px; font-size : 12px; width : 128px; text-align : center; margin-top : 10px; } .diggit { float : left; width : 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; width : 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; } .diggword { margin-top : 5px; margin-left : 0; font-size : 12px; color : #808080; } .clearfix:focus { content : '' ; display : block; clear : both; } </ style>
{% endblock %}{% block content %}< div class = " col-md-3" > < div class = " panel panel-info" > < div class = " panel-heading" > 文章分类</ div> < div class = " panel-body" > {% for category in category_list %}< p> < a href = " /{{ username }}/category/{{ category.2 }}" > {{ category.0 }} ({{ category.1 }})</ a> </ p> {# < p> < a href = " /{{ username }}/category/{{ category.pk }}" > {{ category.name }} ({{ category.count_article_num }})</ a> </ p> #}{% endfor %}</ div> </ div> < div class = " panel panel-success" > < div class = " panel-heading" > 文章标签</ div> < div class = " panel-body" > {% for tag in tag_list %}< p> < a href = " /{{ username }}/tag/{{ tag.2 }}" > {{ tag.0 }} ({{ tag.1 }})</ a> </ p> {% endfor %}</ div> </ div> < div class = " panel panel-danger" > < div class = " panel-heading" > 日期归档</ div> < div class = " panel-body" > {% for date in date_list %}{# < p> < a href = " " > {{ date.0 }} ({{ date.1 }})</ a> </ p> #}< p> < a href = " /{{ username }}/archive/{{ date.month|date:'Y-m' }}" > {{ date.month|date:'Y年m月' }}({{ date.count_article_nums }})</ a> </ p> {% endfor %}</ div> </ div> </ div> < div class = " col-md-9" > < h3 style = " color : #399ab2; " > {{ article_detail.title }}</ h3> < div class = " content" > {{ article_detail.content|safe }}</ div> </ div> {% endblock %}{% block js %}< script> { % comment % } function votePost ( id, flag ) { is_up = flag === 'Digg' ? 0 : 1 ; } { % endcomment % } $ ( ".active" ) . click ( function ( ) { let is_up = $ ( this ) . hasClass ( 'diggit' ) ; var article_id = '{{ article_detail.pk }}' ; var _this = $ ( this ) ; $. ajax ( { url : '/up_and_down/' , type : 'post' , data : { is_up : is_up, article_id : article_id, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( ) { if ( res === 200 ) { $ ( "#digg_tips" ) . text ( res. msg) ; let old_num = _this. children ( ) . text ( ) ; { #_this. children ( ) . text ( parseInt ( old_num) + 1 ) ; #} _this. children ( ) . text ( Number ( old_num) + 1 ) ; } else { $ ( "#digg_tips" ) . html ( res. msg) ; } } , } ) ; } ) ; </ script>
{% endblock %}
2.后端
def article_detail ( request, username, article_id) : print ( article_id) user_obj = models. UserInfo. objects. filter ( username= username) . first( ) print ( user_obj) if not user_obj: '''图片防盗链:通过 Referer参数判断,通过这个参数就可以知道你当前的地址是从哪个网页调过来的,然后做验证 ''' return render( request, '404.html' ) blog = user_obj. blogarticle_detail = models. Article. objects. filter ( pk= article_id) . first( ) category_list = models. Category. objects. filter ( blog= blog) . annotate( count_article_num= Count( 'article__pk' ) ) . values_list( 'name' , 'count_article_num' , 'pk' ) tag_list = models. Tag. objects. filter ( blog= blog) . annotate( count_article_num= Count( 'article__pk' ) ) . values_list( 'name' , 'count_article_num' , 'pk' ) date_list = models. Article. objects. annotate( month= TruncMonth( 'create_time' ) ) . values( 'month' ) . filter ( blog= blog) . annotate( count_article_nums= Count( 'pk' ) ) . values( 'month' , 'count_article_nums' ) comment_list = models. Comment. objects. filter ( article_id= article_id) . all ( ) return render( request, 'article_detail.html' , locals ( ) )
三、点赞点菜
1.前端
{% extends 'home.html' %}{% block css %}< style> .s1 { margin-right : 10px; color : #999; } .content { font-size : 18px; color : #444; } #div_digg { float : right; margin-bottom : 10px; margin-right : 30px; font-size : 12px; width : 128px; text-align : center; margin-top : 10px; } .diggit { float : left; width : 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; width : 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; } .diggword { margin-top : 5px; margin-left : 0; font-size : 12px; color : #808080; } .clearfix:focus { content : '' ; display : block; clear : both; } </ style>
{% endblock %}{% block content %}< div class = " col-md-3" > < div class = " panel panel-info" > < div class = " panel-heading" > 文章分类</ div> < div class = " panel-body" > {% for category in category_list %}< p> < a href = " /{{ username }}/category/{{ category.2 }}" > {{ category.0 }} ({{ category.1 }})</ a> </ p> {# < p> < a href = " /{{ username }}/category/{{ category.pk }}" > {{ category.name }} ({{ category.count_article_num }})</ a> </ p> #}{% endfor %}</ div> </ div> < div class = " panel panel-success" > < div class = " panel-heading" > 文章标签</ div> < div class = " panel-body" > {% for tag in tag_list %}< p> < a href = " /{{ username }}/tag/{{ tag.2 }}" > {{ tag.0 }} ({{ tag.1 }})</ a> </ p> {% endfor %}</ div> </ div> < div class = " panel panel-danger" > < div class = " panel-heading" > 日期归档</ div> < div class = " panel-body" > {% for date in date_list %}{# < p> < a href = " " > {{ date.0 }} ({{ date.1 }})</ a> </ p> #}< p> < a href = " /{{ username }}/archive/{{ date.month|date:'Y-m' }}" > {{ date.month|date:'Y年m月' }}({{ date.count_article_nums }})</ a> </ p> {% endfor %}</ div> </ div> </ div> < div class = " col-md-9" > < h3 style = " color : #399ab2; " > {{ article_detail.title }}</ h3> < div class = " content" > {{ article_detail.content|safe }}</ div> < div class = " clearfix" > < div id = " div_digg" > < div class = " diggit active" onclick = " votePost ( 11647089 , 'Digg' ) " > < span class = " diggnum" id = " digg_count" > {{ article_detail.up_num }}</ span> </ div> < div class = " buryit active" onclick = " votePost ( 11647089 , 'Bury' ) " > < span class = " burynum" id = " bury_count" > {{ article_detail.down_num }}</ span> </ div> < div class = " clear" > </ div> < div class = " diggword" id = " digg_tips" style = " color : red; " > </ div> </ div> </ div> </ div> {% endblock %}{% block js %}< script> { % comment % } function votePost ( id, flag ) { is_up = flag === 'Digg' ? 0 : 1 ; } { % endcomment % } $ ( ".active" ) . click ( function ( ) { let is_up = $ ( this ) . hasClass ( 'diggit' ) ; var article_id = '{{ article_detail.pk }}' ; var _this = $ ( this ) ; $. ajax ( { url : '/up_and_down/' , type : 'post' , data : { is_up : is_up, article_id : article_id, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( ) { if ( res === 200 ) { $ ( "#digg_tips" ) . text ( res. msg) ; let old_num = _this. children ( ) . text ( ) ; { #_this. children ( ) . text ( parseInt ( old_num) + 1 ) ; #} _this. children ( ) . text ( Number ( old_num) + 1 ) ; } else { $ ( "#digg_tips" ) . html ( res. msg) ; } } , } ) ; } ) ; </ script>
{% endblock %}
2.后端
def up_and_down ( request) : '''分析点赞点彩的实现逻辑:1.必须判断用户是否登陆了。如果没有则在前端页面显示登录2.若是第一次登录:2.1 点赞数加 12.2 在页面上显示点赞成功3.如果已经点击过,就提示不让他再点了4.如果是第一次点击,应该在处理哪些逻辑4.1 肯定需要在点赞点彩表中增加一条记录4.2 还需要更新文章中的up_num或者down_num字段5. 取消点赞或者点彩功能-----》收藏:param request::return:''' if request. method == 'POST' : back_dict = { 'code' : 200 , 'msg' : '支持成功' } is_up = request. POST. get( 'is_UP' ) is_up = json. loads( is_up) article_id = request. POST. get( 'article_id' ) if not request. session. get( 'username' ) : back_dict[ 'code' ] = 1400 back_dict[ 'msg' ] = '请先<a href="/login/" style="color: red;">登录</a>' return JsonResponse( back_dict) res = models. UpAndDown. objects. filter ( article_id= article_id, user_id= request. session. get( 'id' ) ) . first( ) if res: back_dict[ 'code' ] = 1401 back_dict[ 'msg' ] = '你已经支持过了' return JsonResponse( back_dict) if is_up: models. Article. objects. create( pk= article_id) . update( up_num= F( 'up_num' ) + 1 ) else : models. Article. objects. filter ( pk= article_id) . update( down_num= F( 'down_num' ) + 1 ) back_dict[ 'msg' ] = '支持成功' models. UpAndDown. objects. create( is_up= is_up, article_id= article_id, user_id= request. session. get( 'id' ) ) return JsonResponse( back_dict)
四、评论功能
1.根评论前端
{% extends 'home.html' %}{% block css %}< style> .s1 { margin-top : 10px; color : #999; } .content { font-size : 16px; color : #444; } #div_digg { float : right; margin-bottom : 10px; margin-right : 30px; font-size : 12px; width : 128px; text-align : center; margin-top : 10px; } .diggit { float : left; width : 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; width : 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; } .diggword { margin-top : 5px; margin-left : 0; font-size : 12px; color : #808080; } { # 父标签塌陷 #} .clearfix { content : "" ; display : block; clear : both; } </ style>
{% endblock %}{% block content %}< div class = " col-md-3" > < div class = " panel panel-success" > < div class = " panel-heading" > 文章分类</ div> < div class = " panel-body" > {% for cate in cate_list %}{# < p> < a href = " " > {{ cate.name }}({{ cate.1 }})</ a> </ p> #}< p> < a href = " /{{ username }}/category/{{ cate.2 }}" > {{ cate.0 }}({{ cate.1 }})</ a> </ p> {% endfor %}</ div> </ div> < div class = " panel panel-info" > < div class = " panel-heading" > 文章标签</ div> < div class = " panel-body" > {% for tag in tag_list %}{# < p> < a href = " /{{ username }}/tag/{{ tag.2 }}" > {{ tag.0 }}({{ tag.1 }})</ a> </ p> #}< p> < a href = " /{{ username }}/tag/{{ tag.2 }}" > {{ tag.0 }}({{ tag.1 }})</ a> </ p> {% endfor %}</ div> </ div> < div class = " panel panel-danger" > < div class = " panel-heading" > 日期归档</ div> < div class = " panel-body" > {% for date in date_list %}< p> < a href = " /{{ username }}/archive/{{ date.month|date:'Y-m' }}" > {{ date.month|date:'Y年m月' }}({{ date.c }})</ a> </ p> {% endfor %}</ div> </ div> </ div> < div class = " col-md-9" > < h3 style = " color : #9cba39" > < a href = " " > {{ article_detail.title }}</ a> </ h3> < div class = " content" > {{ article_detail.content|safe }}</ div> < div class = " clearfix" > < div id = " div_digg" > < div class = " diggit active" onclick = " votePost ( 12834355 , 'Digg' ) " > < span class = " diggnum" id = " digg_count" > {{ article_detail.up_num }}</ span> </ div> < div class = " buryit active" onclick = " votePost ( 12834355 , 'Bury' ) " > < span class = " burynum" id = " bury_count" > {{ article_detail.down_num }}</ span> </ div> < div class = " clear" > </ div> < div class = " diggword" id = " digg_tips" style = " color : red; " > </ div> </ div> </ div> < div class = " comment_list" > < h4> < span class = " glyphicon glyphicon-comment" > </ span> 评论列表</ h4> < ul class = " list-group" > {% for comment in comment_list %}< li class = " list-group-item" > < span style = " margin-right : 10px; " > #{{ forloop.counter }}楼</ span> < span style = " margin-right : 10px; " > {{ comment.comment_time }}</ span> < span style = " margin-right : 10px; " > {{ comment.user.username }}</ span> < span style = " margin-right : 10px; " class = " pull-right" > < a href = " #" > 回复</ a> </ span> < div class = " content" style = " margin-left : 14px; " > 你好啊</ div> </ li> {% endfor %}</ ul> </ div> < div class = " comment" > < p> < span class = " glyphicon glyphicon-comment" > 发表评论</ span> </ p> < p> < textarea name = " " id = " content" cols = " 30" rows = " 10" > </ textarea> </ p> < p> < button class = " btn btn-success btn_comment" > 提交评论</ button> </ p> </ div> </ div>
{% endblock %}{% block js %}< script> < ! -- 点赞点踩样式开始 -- > { % comment % } function onclick ( id, flag ) { { #if ( flag === "Digg" ) { } else { } #} { #var is_up = flag === 'Digg' ? 0 : 1 ; #} } { % endcomment % } $ ( ".active" ) . click ( function ( ) { let is_up = $ ( this ) . hasClass ( "diggit" ) ; var article_id = '{{ article_detail.pk }}' var _this = $ ( this ) ; $. ajax ( { url : '/up_and_down/' , type : 'post' , data : { is_up : is_up, article_id : article_id, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( res ) { if ( res. code === 200 ) { $ ( "#digg_tips" ) . text ( res. msg) ; { #let old_num = parseInt ( _this. children ( ) . text ( ) ) ; #} let old_num = Number ( _this. children ( ) . text ( ) ) ; _this. children ( ) . text ( old_num + 1 ) ; } else { $ ( "#digg_tips" ) . html ( res. msg) } } } ) ; } ) ; < ! -- 点赞点踩样式结束 -- > < ! -- 评论功能开始 -- > $ ( ".btn_comment" ) . click ( function ( ) { { #alert ( 123 ) ; #} var article_id = '{{ article_detail.pk }}' ; let content = $ ( "#content" ) . val ( ) ; $. ajax ( { url : '/comment/' , type : 'post' , data : { article_id : article_id, content : content, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( res ) { var username = '{{ request.session.username }}' ; let html = ` <li class="list-group-item"><span style="margin-right: 10px;"><span class="glyphicon glyphicon-comment"></span> ${ username} </span><div class="content" style="margin-left: 14px;"> ${ content} </div></li> ` ; $ ( ".list-group" ) . append ( html) ; $ ( "#content" ) . val ( '' ) ; } } ) ; } ) ; < ! -- 评论功能结束 -- > </ script>
{% endblock %}
2.根评论后端
def comment ( request) : '''分析评论的逻辑:1.登录之后才能评论2.评论的内容要入库1.操作文章表,2.评论表:param request::return:''' back_dict = { 'code' : 200 , 'msg' : '支持成功' } article_id = request. POST. get( 'article_id' ) content = request. POST. get( 'content' ) parent_id = request. POST. get( 'parent_id' ) if not request. session. get( 'username' ) : back_dict[ 'code' ] = 1404 back_dict[ 'msg' ] = '请先登录之后再评论' return JsonResponse( back_dict) from django. db import transactiontry : with transaction. atomic( ) : models. Article. objects. filter ( pk= article_id) . update( comment_num= F( 'comment_num' ) + 1 ) models. Comment. objects. create( content= content, article_id= article_id, parent_id= parent_id, user_id= request. session. get( 'id' ) ) except : . . . transaction. rollback( ) return JsonResponse( back_dict)
3.子评论前端
{ % extends 'home.html' % } { % block css % } < style> . s1 { margin- top: 10px; color : #999 ; } . content { font- size: 16px; color : #444 ; } #div_digg { float : right; margin- bottom: 10px; margin- right: 30px; font- size: 12px; width : 128px; text- align: center; margin- top: 10px; } . diggit { float : left; width : 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; width : 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; } . diggword { margin- top: 5px; margin- left: 0 ; font- size: 12px; color : #808080 ; } { # 父标签塌陷 #} . clearfix { content : "" ; display : block; clear : both; } < / style>
{ % endblock % } { % block content % } < div class = "col-md-3" > < ! -- 带标题的面板 -- > < div class = "panel panel-success" > < div class = "panel-heading" > 文章分类< / div> < div class = "panel-body" > { % for cate in cate_list % } { # < p> < a href= "" > { { cate. name } } ( { { cate. 1 } } ) < / a> < / p> #} < p> < a href= "/{{ username }}/category/{{ cate.2 }}" > { { cate. 0 } } ( { { cate. 1 } } ) < / a> < / p> { % endfor % } < / div> < / div> < div class = "panel panel-info" > < div class = "panel-heading" > 文章标签< / div> < div class = "panel-body" > { % for tag in tag_list % } < ! -- tag. 0 是标签名称 tag. 1 是标签数量 -- > { # < p> < a href= "/{{ username }}/tag/{{ tag.2 }}" > { { tag. 0 } } ( { { tag. 1 } } ) < / a> < / p> #} < p> < a href= "/{{ username }}/tag/{{ tag.2 }}" > { { tag. 0 } } ( { { tag. 1 } } ) < / a> < / p> { % endfor % } < / div> < / div> < div class = "panel panel-danger" > < div class = "panel-heading" > 日期归档< / div> < div class = "panel-body" > { % for date in date_list % } < p> < a href= "/{{ username }}/archive/{{ date.month|date:'Y-m' }}" > { { date. month| date: 'Y年m月' } } ( { { date. c } } ) < / a> < / p> { % endfor % } < / div> < / div> < / div> < div class = "col-md-9" > < h3 style= "color: #9cba39" > < a href= "" > { { article_detail. title } } < / a> < / h3> < div class = "content" > { { article_detail. content| safe } } < / div> < ! -- 点赞点踩样式开始 -- > < div class = "clearfix" > < div id= "div_digg" > < ! -- 点赞 -- > < div class = "diggit active" onclick= "votePost(12834355,'Digg')" > < span class = "diggnum" id= "digg_count" > { { article_detail. up_num } } < / span> < / div> < ! -- 点踩 -- > < div class = "buryit active" onclick= "votePost(12834355,'Bury')" > < span class = "burynum" id= "bury_count" > { { article_detail. down_num } } < / span> < / div> < div class = "clear" > < / div> < div class = "diggword" id= "digg_tips" style= "color: red;" > < / div> < / div> < / div> < ! -- 点赞点踩样式结束 -- > < ! -- 评论列表的展示开始 -- > < div class = "comment_list" > < h4> < span class = "glyphicon glyphicon-comment" > < / span> 评论列表< / h4> < ul class = "list-group" > { % for comment in comment_list % } < li class = "list-group-item" > < span style= "margin-right: 10px;" > #{ { forloop. counter } } 楼< / span> < span style= "margin-right: 10px;" > { { comment. comment_time } } < / span> < span style= "margin-right: 10px;" > { { comment. user. username } } < / span> < ! -- href= "javascript;" 防止页面跳转,这是由于锚点的缘故,若是href= "" 会自动刷新页面到最上面 -- > < span style= "margin-right: 10px;" class = "pull-right" > < a href= "javascript:;" comment_username= "{{ comment.user.username }}" comment_id= "{{ comment.pk }}" class = "reply" > 回复< / a> < / span> < div class = "content" style= "margin-left: 14px;" > < ! -- 若是根评论则直接显示评论内容,子评论需要@+ 当前评论者 -- > { % if comment. parent % } { { comment. content } } { % else % } < p> @ { { comment. parent. user. username } } < / p> { { comment. content } } { % endif % } < / div> < / li> { % endfor % } < / ul> < / div> < ! -- 评论列表的展示结束 -- > < ! -- 评论功能开始 -- > < div class = "comment" > < p> < span class = "glyphicon glyphicon-comment" > 发表评论< / span> < / p> < p> < textarea name= "" id= "content" cols= "30" rows= "10" > < / textarea> < / p> < p> < button class = "btn btn-success btn_comment" > 提交评论< / button> < / p> < / div> < ! -- 评论功能结束 -- > < / div>
{ % endblock % } { % block js % } < script> { #< ! -- 点赞点踩样式开始 -- > #} { % comment % } function onclick ( id, flag ) { { #if ( flag === "Digg" ) { } else { } #} { #var is_up = flag === 'Digg' ? 0 : 1 ; #} } { % endcomment % } $ ( ".active" ) . click ( function ( ) { let is_up = $ ( this ) . hasClass ( "diggit" ) ; var article_id = '{{ article_detail.pk }}' var _this = $ ( this ) ; $. ajax ( { url : '/up_and_down/' , type : 'post' , data : { is_up : is_up, article_id : article_id, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( res ) { if ( res. code === 200 ) { $ ( "#digg_tips" ) . text ( res. msg) ; { #let old_num = parseInt ( _this. children ( ) . text ( ) ) ; #} let old_num = Number ( _this. children ( ) . text ( ) ) ; _this. children ( ) . text ( old_num + 1 ) ; } else { $ ( "#digg_tips" ) . html ( res. msg) } } } ) ; } ) ; < ! -- 点赞点踩样式结束 -- > var parent_id = null ; < ! -- 根评论功能开始 -- > $ ( ".btn_comment" ) . click ( function ( ) { { #alert ( 123 ) ; #} var article_id = '{{ article_detail.pk }}' ; let content = $ ( "#content" ) . val ( ) ; if ( parent_id) { let indexOf_num = content. indexOf ( '\n' ) ; content = content. slice ( indexOf_num) ; } $. ajax ( { url : '/comment/' , type : 'post' , data : { article_id : article_id, content : content, parent_id : parent_id, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( res ) { var username = '{{ request.session.username }}' ; let html = ` <li class="list-group-item"><span style="margin-right: 10px;"><span class="glyphicon glyphicon-comment"></span> ${ username} </span><div class="content" style="margin-left: 14px;"> ${ content} </div></li> ` ; $ ( ".list-group" ) . append ( html) ; $ ( "#content" ) . val ( '' ) ; } } ) ; } ) ; < ! -- 根评论功能结束 -- > < ! -- 子评论功能开始 -- > $ ( ".reply" ) . click ( function ( ) { let comment_username = $ ( this ) . attr ( 'comment_username' ) ; parent_id = $ ( this ) . attr ( 'comment_id' ) ; $ ( "#content" ) . val ( "@" + comment_username + '\n' ) . focus ( ) ; } ) ; < ! -- 子评论功能结束 -- > < / script>
{ % endblock % }
子评论后端
def article_detail ( request, username, article_id) : print ( article_id) user_obj = models. UserInfo. objects. filter ( username= username) . first( ) print ( 'user_obj:' , user_obj) if not user_obj: '''图片防盗链:通过 Referer参数判断,通过这个参数就可以知道你当前的地址是从哪个网页调过来的,然后做验证 ''' return render( request, '404.html' ) blog = user_obj. blogarticle_detail = models. Article. objects. filter ( pk= article_id) . first( ) cate_list = models. Category. objects. filter ( blog= blog) . annotate( count_article_num= Count( 'article__pk' ) ) . values_list( 'name' , 'count_article_num' , 'pk' ) print ( cate_list) tag_list = models. Tag. objects. filter ( blog= blog) . annotate( count_article_num= Count( 'article__pk' ) ) . values_list( 'name' , 'count_article_num' , 'pk' ) date_list = models. Article. objects. annotate( month= TruncMonth( 'create_time' ) ) . values( 'month' ) . filter ( blog= blog) . annotate( count_article_nums= Count( 'pk' ) ) . values( 'month' , 'count_article_nums' ) comment_list = models. Comment. objects. filter ( article_id= article_id) . all ( ) return render( request, 'article_detail.html' , locals ( ) )
def comment ( request) : '''分析评论的逻辑:1.必须登录才能评论2.评论的内容要入库1.操作文章表2.评论表:param request::return:''' if request. method == 'POST' : back_dict = { 'code' : 200 , 'msg' : '密码修改成功,3秒之后自动跳转页面' , 'data' : [ ] } article_id = request. POST. get( 'article_id' ) content = request. POST. get( 'content' ) parent_id = request. POST. get( 'parent_id' ) if not request. session. get( 'username' ) : back_dict[ 'code' ] = 5001 back_dict[ 'msg' ] = '请先登录之后再评论' return JsonResponse( back_dict) from django. db import transactiontry : with transaction. atomic( ) : models. Article. objects. filter ( pk= article_id) . update( comment_num= F( 'comment_num' ) + 1 ) models. Comment. objects. create( content= content, article_id= article_id, user_id= request. session. get( 'id' ) , parent_id= parent_id) except : ctime = datetime. datetime. today( ) logger = get_logger( ) logger. debug( '{}在{}注册了账号' . format ( request. session. get( 'username' ) , ctime) ) transaction. rollback( ) return JsonResponse( back_dict)
五、评论分页
1.前端
{ % extends 'home.html' % } { % block css % } < style> . s1 { margin- top: 10px; color : #999 ; } . content { font- size: 16px; color : #444 ; } #div_digg { float : right; margin- bottom: 10px; margin- right: 30px; font- size: 12px; width : 128px; text- align: center; margin- top: 10px; } . diggit { float : left; width : 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; width : 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; } . diggword { margin- top: 5px; margin- left: 0 ; font- size: 12px; color : #808080 ; } { # 父标签塌陷 #} . clearfix { content : "" ; display : block; clear : both; } < / style>
{ % endblock % } { % block content % } < div class = "col-md-3" > < ! -- 带标题的面板 -- > < div class = "panel panel-success" > < div class = "panel-heading" > 文章分类< / div> < div class = "panel-body" > { % for cate in cate_list % } { # < p> < a href= "" > { { cate. name } } ( { { cate. 1 } } ) < / a> < / p> #} < p> < a href= "/{{ username }}/category/{{ cate.2 }}" > { { cate. 0 } } ( { { cate. 1 } } ) < / a> < / p> { % endfor % } < / div> < / div> < div class = "panel panel-info" > < div class = "panel-heading" > 文章标签< / div> < div class = "panel-body" > { % for tag in tag_list % } < ! -- tag. 0 是标签名称 tag. 1 是标签数量 -- > { # < p> < a href= "/{{ username }}/tag/{{ tag.2 }}" > { { tag. 0 } } ( { { tag. 1 } } ) < / a> < / p> #} < p> < a href= "/{{ username }}/tag/{{ tag.2 }}" > { { tag. 0 } } ( { { tag. 1 } } ) < / a> < / p> { % endfor % } < / div> < / div> < div class = "panel panel-danger" > < div class = "panel-heading" > 日期归档< / div> < div class = "panel-body" > { % for date in date_list % } < p> < a href= "/{{ username }}/archive/{{ date.month|date:'Y-m' }}" > { { date. month| date: 'Y年m月' } } ( { { date. c } } ) < / a> < / p> { % endfor % } < / div> < / div> < / div> < div class = "col-md-9" > < h3 style= "color: #9cba39" > < a href= "" > { { article_detail. title } } < / a> < / h3> < div class = "content" > { { article_detail. content| safe } } < / div> < ! -- 点赞点踩样式开始 -- > < div class = "clearfix" > < div id= "div_digg" > < ! -- 点赞 -- > < div class = "diggit active" onclick= "votePost(12834355,'Digg')" > < span class = "diggnum" id= "digg_count" > { { article_detail. up_num } } < / span> < / div> < ! -- 点踩 -- > < div class = "buryit active" onclick= "votePost(12834355,'Bury')" > < span class = "burynum" id= "bury_count" > { { article_detail. down_num } } < / span> < / div> < div class = "clear" > < / div> < div class = "diggword" id= "digg_tips" style= "color: red;" > < / div> < / div> < / div> < ! -- 点赞点踩样式结束 -- > < ! -- 评论列表的展示开始 -- > < div class = "comment_list" > < h4> < span class = "glyphicon glyphicon-comment" > < / span> 评论列表< / h4> < ul class = "list-group" > { % for comment in comment_list % } < li class = "list-group-item" > < span style= "margin-right: 10px;" > #{ { forloop. counter } } 楼< / span> < span style= "margin-right: 10px;" > { { comment. comment_time } } < / span> < span style= "margin-right: 10px;" > { { comment. user. username } } < / span> < ! -- href= "javascript;" 防止页面跳转,这是由于锚点的缘故,若是href= "" 会自动刷新页面到最上面 -- > < span style= "margin-right: 10px;" class = "pull-right" > < a href= "javascript:;" comment_username= "{{ comment.user.username }}" comment_id= "{{ comment.pk }}" class = "reply" > 回复< / a> < / span> < div class = "content" style= "margin-left: 14px;" > < ! -- 若是根评论则直接显示评论内容,子评论需要@+ 当前评论者 -- > { % if comment. parent % } { { comment. content } } { % else % } < p> @ { { comment. parent. user. username } } < / p> { { comment. content } } { % endif % } < / div> < / li> { % endfor % } < / ul> < / div> < ! -- 评论列表的展示结束 -- > < ! -- 分页功能开始 -- > < div class = "text-center" > { { page_obj. page_html| safe } } < / div> < ! -- 分页功能结束 -- > < ! -- 评论功能开始 -- > < div class = "comment" > < p> < span class = "glyphicon glyphicon-comment" > 发表评论< / span> < / p> < p> < textarea name= "" id= "content" cols= "30" rows= "10" > < / textarea> < / p> < p> < button class = "btn btn-success btn_comment" > 提交评论< / button> < / p> < / div> < ! -- 评论功能结束 -- > < / div>
{ % endblock % } { % block js % } < script> { #< ! -- 点赞点踩样式开始 -- > #} { % comment % } function onclick ( id, flag ) { { #if ( flag === "Digg" ) { } else { } #} { #var is_up = flag === 'Digg' ? 0 : 1 ; #} } { % endcomment % } $ ( ".active" ) . click ( function ( ) { let is_up = $ ( this ) . hasClass ( "diggit" ) ; var article_id = '{{ article_detail.pk }}' var _this = $ ( this ) ; $. ajax ( { url : '/up_and_down/' , type : 'post' , data : { is_up : is_up, article_id : article_id, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( res ) { if ( res. code === 200 ) { $ ( "#digg_tips" ) . text ( res. msg) ; { #let old_num = parseInt ( _this. children ( ) . text ( ) ) ; #} let old_num = Number ( _this. children ( ) . text ( ) ) ; _this. children ( ) . text ( old_num + 1 ) ; } else { $ ( "#digg_tips" ) . html ( res. msg) } } } ) ; } ) ; < ! -- 点赞点踩样式结束 -- > var parent_id = null ; < ! -- 根评论功能开始 -- > $ ( ".btn_comment" ) . click ( function ( ) { { #alert ( 123 ) ; #} var article_id = '{{ article_detail.pk }}' ; let content = $ ( "#content" ) . val ( ) ; if ( parent_id) { let indexOf_num = content. indexOf ( '\n' ) ; content = content. slice ( indexOf_num) ; } $. ajax ( { url : '/comment/' , type : 'post' , data : { article_id : article_id, content : content, parent_id : parent_id, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( res ) { var username = '{{ request.session.username }}' ; let html = ` <li class="list-group-item"><span style="margin-right: 10px;"><span class="glyphicon glyphicon-comment"></span> ${ username} </span><div class="content" style="margin-left: 14px;"> ${ content} </div></li> ` ; $ ( ".list-group" ) . append ( html) ; $ ( "#content" ) . val ( '' ) ; } } ) ; } ) ; < ! -- 根评论功能结束 -- > < ! -- 子评论功能开始 -- > $ ( ".reply" ) . click ( function ( ) { let comment_username = $ ( this ) . attr ( 'comment_username' ) ; parent_id = $ ( this ) . attr ( 'comment_id' ) ; $ ( "#content" ) . val ( "@" + comment_username + '\n' ) . focus ( ) ; } ) ; < ! -- 子评论功能结束 -- > < ! -- 评论分页功能开始 -- > $ ( ".btn_page" ) . click ( function ( ) { let current_page = $ ( this ) . attr ( 'current_page' ) ; var article_id = '{{ article_detail.pk }}' ; $ ( ".active" ) . removeClass ( 'active' ) ; $ ( this ) . parent ( ) . addClass ( 'active' ) ; $. ajax ( { url : '/comment_page/' , type : 'post' , data : { current_page : current_page, article_id : article_id, csrfmiddlewaretoken : '{{ csrf_token }}' } , success : function ( res ) { console. log ( res) ; if ( res. code === 200 ) { var html = "" ; $. each ( res. data, function ( index, obj ) { console. log ( obj) ; html += ` <li class="list-group-item"><span style="margin-right: 10px;"># ${ obj. forloop} 楼</span><span style="margin-right: 10px;"> ${ obj. comment_time} </span><span style="margin-right: 10px;"> ${ obj. username} </span><span style="margin-right: 10px;" class="pull-right"><a href="javascript:;" comment_username=" ${ obj. username} "comment_id=" ${ obj. pk} " class="reply">回复</a></span><div class="content" style="margin-left: 14px;"><!-- 若是根评论则直接显示评论内容,子评论需要@+当前评论者 --> ${ obj. content} </div></li> ` ; } ) $ ( ".list-group" ) . html ( html) ; } } , } ) ; } ) ; < ! -- 评论分页功能结束 -- > < / script>
{ % endblock % }
2.后端
def article_detail ( request, username, article_id) : print ( article_id) user_obj = models. UserInfo. objects. filter ( username= username) . first( ) print ( 'user_obj:' , user_obj) if not user_obj: '''图片防盗链:通过 Referer参数判断,通过这个参数就可以知道你当前的地址是从哪个网页调过来的,然后做验证 ''' return render( request, '404.html' ) blog = user_obj. blogarticle_detail = models. Article. objects. filter ( pk= article_id) . first( ) cate_list = models. Category. objects. filter ( blog= blog) . annotate( count_article_num= Count( 'article__pk' ) ) . values_list( 'name' , 'count_article_num' , 'pk' ) print ( cate_list) tag_list = models. Tag. objects. filter ( blog= blog) . annotate( count_article_num= Count( 'article__pk' ) ) . values_list( 'name' , 'count_article_num' , 'pk' ) date_list = models. Article. objects. annotate( month= TruncMonth( 'create_time' ) ) . values( 'month' ) . filter ( blog= blog) . annotate( count_article_nums= Count( 'pk' ) ) . values( 'month' , 'count_article_nums' ) comment_list = models. Comment. objects. filter ( article_id= article_id) . all ( ) from utils. mypage1 import Paginationcurrent_page = request. GET. get( 'page' ) try : current_page = int ( current_page) except : current_page = 1 all_count = comment_list. count( ) page_obj = Pagination( current_page, all_count, per_page_num= 5 ) comment_list = comment_list[ page_obj. start: page_obj. end] return render( request, 'article_detail.html' , locals ( ) )
def comment ( request) : '''分析评论的逻辑:1.必须登录才能评论2.评论的内容要入库1.操作文章表2.评论表:param request::return:''' if request. method == 'POST' : back_dict = { 'code' : 200 , 'msg' : '密码修改成功,3秒之后自动跳转页面' , 'data' : [ ] } article_id = request. POST. get( 'article_id' ) content = request. POST. get( 'content' ) parent_id = request. POST. get( 'parent_id' ) if not request. session. get( 'username' ) : back_dict[ 'code' ] = 5001 back_dict[ 'msg' ] = '请先登录之后再评论' return JsonResponse( back_dict) from django. db import transactiontry : with transaction. atomic( ) : models. Article. objects. filter ( pk= article_id) . update( comment_num= F( 'comment_num' ) + 1 ) models. Comment. objects. create( content= content, article_id= article_id, user_id= request. session. get( 'id' ) , parent_id= parent_id) except : ctime = datetime. datetime. today( ) logger = get_logger( ) logger. debug( '{}在{}注册了账号' . format ( request. session. get( 'username' ) , ctime) ) transaction. rollback( ) return JsonResponse( back_dict)
def comment_page ( request) : if request. method == 'POST' : back_dict = { 'code' : 200 , 'msg' : '查询成功' } current_page = request. POST. get( 'current_page' ) try : current_page = int ( current_page) except : current_page = 1 article_id = request. POST. get( 'article_id' ) if not current_page: back_dict[ 'code' ] = 6001 back_dict[ 'msg' ] = '当前页数据有误或为空' JsonResponse( back_dict) per_page_num = 5. start_page = ( current_page - 1 ) * per_page_numend_page = current_page * per_page_numcomment_list = models. Comment. objects. filter ( article_id= article_id) . all ( ) [ start_page: end_page] comment_list_obj = [ ] i = 1 for comment in comment_list: comment_list_obj. append( { 'forloop' : i, 'pk' : comment. pk, 'comment_time' : comment. comment_time, 'username' : comment. user. username, 'content' : comment. content} ) i += 1 print ( comment_list_obj) back_dict[ 'data' ] = comment_list_objreturn JsonResponse( back_dict)
3.分页的代码
1.原始的分页代码
class Pagination ( object ) : def __init__ ( self, current_page, all_count, per_page_num= 2 , pager_count= 11 ) : """封装分页相关数据:param current_page: 当前页:param all_count: 数据库中的数据总条数:param per_page_num: 每页显示的数据条数:param pager_count: 最多显示的页码个数""" try : current_page = int ( current_page) except Exception as e: current_page = 1 if current_page < 1 : current_page = 1 self. current_page = current_pageself. all_count = all_countself. per_page_num = per_page_numall_pager, tmp = divmod ( all_count, per_page_num) if tmp: all_pager += 1 self. all_pager = all_pagerself. pager_count = pager_countself. pager_count_half = int ( ( pager_count - 1 ) / 2 ) @property def start ( self) : return ( self. current_page - 1 ) * self. per_page_num@property def end ( self) : return self. current_page * self. per_page_numdef page_html ( self) : if self. all_pager <= self. pager_count: pager_start = 1 pager_end = self. all_pager + 1 else : if self. current_page <= self. pager_count_half: pager_start = 1 pager_end = self. pager_count + 1 else : if ( self. current_page + self. pager_count_half) > self. all_pager: pager_end = self. all_pager + 1 pager_start = self. all_pager - self. pager_count + 1 else : pager_start = self. current_page - self. pager_count_halfpager_end = self. current_page + self. pager_count_half + 1 page_html_list = [ ] page_html_list. append( '''<nav aria-label='Page navigation>'<ul class='pagination'>''' ) first_page = '<li><a href="?page=%s">首页</a></li>' % ( 1 ) page_html_list. append( first_page) if self. current_page <= 1 : prev_page = '<li class="disabled"><a href="#">上一页</a></li>' else : prev_page = '<li><a href="?page=%s">上一页</a></li>' % ( self. current_page - 1 , ) page_html_list. append( prev_page) for i in range ( pager_start, pager_end) : if i == self. current_page: temp = '<li class="active"><a href="?page=%s">%s</a></li>' % ( i, i, ) else : temp = '<li><a href="?page=%s">%s</a></li>' % ( i, i, ) page_html_list. append( temp) if self. current_page >= self. all_pager: next_page = '<li class="disabled"><a href="#">下一页</a></li>' else : next_page = '<li><a href="?page=%s">下一页</a></li>' % ( self. current_page + 1 , ) page_html_list. append( next_page) last_page = '<li><a href="?page=%s">尾页</a></li>' % ( self. all_pager, ) page_html_list. append( last_page) page_html_list. append( '''</nav></ul>''' ) return '' . join( page_html_list)
2.优化后的页面不再刷新的分页代码
class Pagination ( object ) : def __init__ ( self, current_page, all_count, per_page_num= 2 , pager_count= 11 ) : """封装分页相关数据:param current_page: 当前页:param all_count: 数据库中的数据总条数:param per_page_num: 每页显示的数据条数:param pager_count: 最多显示的页码个数""" try : current_page = int ( current_page) except Exception as e: current_page = 1 if current_page < 1 : current_page = 1 self. current_page = current_pageself. all_count = all_countself. per_page_num = per_page_numall_pager, tmp = divmod ( all_count, per_page_num) if tmp: all_pager += 1 self. all_pager = all_pagerself. pager_count = pager_countself. pager_count_half = int ( ( pager_count - 1 ) / 2 ) @property def start ( self) : return ( self. current_page - 1 ) * self. per_page_num@property def end ( self) : return self. current_page * self. per_page_numdef page_html ( self) : if self. all_pager <= self. pager_count: pager_start = 1 pager_end = self. all_pager + 1 else : if self. current_page <= self. pager_count_half: pager_start = 1 pager_end = self. pager_count + 1 else : if ( self. current_page + self. pager_count_half) > self. all_pager: pager_end = self. all_pager + 1 pager_start = self. all_pager - self. pager_count + 1 else : pager_start = self. current_page - self. pager_count_halfpager_end = self. current_page + self. pager_count_half + 1 page_html_list = [ ] page_html_list. append( '''<nav aria-label='Page navigation>'<ul class='pagination'>''' ) first_page = '<li><a href="?page=%s">首页</a></li>' % ( 1 ) page_html_list. append( first_page) if self. current_page <= 1 : prev_page = '<li class="disabled"><a href="#">上一页</a></li>' else : prev_page = '<li><a href="?page=%s">上一页</a></li>' % ( self. current_page - 1 , ) page_html_list. append( prev_page) for i in range ( pager_start, pager_end) : if i == self. current_page: temp = '<li class="active"><a href="javascript:;" class="btn_page" current_page="%s">%s</a></li>' % ( i, i) else : temp = '<li><a href="javascript:;" class="btn_page" current_page="%s">%s</a></li>' % ( i, i) page_html_list. append( temp) if self. current_page >= self. all_pager: next_page = '<li class="disabled"><a href="#">下一页</a></li>' else : next_page = '<li><a href="?page=%s">下一页</a></li>' % ( self. current_page + 1 , ) page_html_list. append( next_page) last_page = '<li><a href="?page=%s">尾页</a></li>' % ( self. all_pager, ) page_html_list. append( last_page) page_html_list. append( '''</nav></ul>''' ) return '' . join( page_html_list)