一、路由
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}),re_path('(?P<username>\w+)/(?P<article_id>\d+)', views.article_detail),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+)', 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'] = 1400back_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'] = 1401back_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-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 class="comment_list"><h3><span class="glyphicon glyphicon-comment"></span>评论列表</h3><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.parent.user.username }}</span>#}<span style="margin-right: 10px;">{{ comment.user.username }}</span><span style="margin-right: 10px;" class="pull-right"><a href="javascript:;" comment_username="{{ comment.user.username }}"comment_id="{{ comment.pk }}" class="repay">回复</a></span><div class="content" style="margin-left: 14px;">{% if comment.parent %}{{ comment.content }}{% else %}<p>@ {{ comment.parent.user.username }}</p><p>{{ comment.content }}</p>{% 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 comment_content">提交评论</button></p></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);}},});});var parent_id = null;<!-- 评论功能开始 -->$(".comment_content").click(function () {var article_id = '{{ article_detail.pk }}';var content = $('#content').val();if (parent_id) {let sub_number = content.indexOf('\n' + '');content = content.slice(sub_number);}$.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 }}';var 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('')},});});<!-- 评论功能结束 --><!-- 子评论功能开始 -->$(".repay").click(function () {let comment_username = $(this).attr('comment_username');parent_id = $(this).attr("comment_id");$("#content").val('@' + comment_username + '\n').focus();});<!-- 子评论功能结束 --></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'] = 1404back_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)