模板继承即渲染:
文章点赞或反对:
跟评论和子评论:
settings.py
settings.py
USE_TZ = False # 转时区改为False
编写url:
urls.py
from django.urls import re_path
urlpatterns = [
...
path('comment/', views.comment), # 评论
# 文章点赞和反对
path('digg/', views.digg),
# 文章详情页展示
re_path('^(?P<username>\w+)/articles/(?P<articles_id>\d+)$', views.article_detail),
]
编写视图:
views.py
import json
from django.shortcuts import render
from django.http import JsonResponse
from django.db.models import F
from blog import models
def article_detail(request, username, articles_id):
article_obj = models.Article.objects.filter(pk=articles_id).first()
comment_list = models.Comment.objects.filter(article_id=articles_id)
return render(request, "article_detail.html", locals())
def digg(request):
article_id = request.POST.get('article_id')
is_up = json.loads(request.POST.get('is_up'))
user_id = request.user.pk
# 过滤重复点赞
obj = models.ArticleUpDown.objects.filter(user_id=user_id, article_id=article_id).first()
response = {"static": True}
if not obj:
ard = models.ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=is_up)
queryset = models.Article.objects.filter(pk=article_id)
if is_up: # 文章点赞数的数据同步
queryset.update(up_count=F("up_count")+1)
else:
queryset.update(down_count=F("down_count")+1)
else:
response['static'] = False
response['handled'] = obj.is_up
return JsonResponse(response)
def comment(request):
article_id = request.POST.get('article_id')
pid = request.POST.get('pid')
content = request.POST.get('content')
user_id = request.user.pk
comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content, parent_comment_id=pid)
response = {}
response["create_time"] = comment_obj.create_time.strftime("%Y-%m-%d %X")
response["username"] = request.user.username
response["content"] = content
return JsonResponse(response)
编写模板,并继承模板:
base.html
{% extends 'base.html' %}
{% load static %}
{% load my_tags %}
{% block css %}
<style>
#div_digg {
float: right;
margin-bottom: 10px;
margin-right: 30px;
font-size: 12px;
width: 125px;
text-align: center;
margin-top: 10px;
}
.diggit {
float: left;
width: 46px;
height: 52px;
background: url({% static 'blog/font/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 'blog/font/downdown.gif' %}) no-repeat;
text-align: center;
cursor: pointer;
margin-top: 2px;
padding-top: 5px;
}
.clear {
clear: both;
}
input.author {
background-image: url({% static 'blog/font/icon_form.gif' %});
background-repeat: no-repeat;
border: 1px solid #ccc;
padding: 4px 4px 4px 30px;
width: 300px;
font-size: 13px;
background-position: 3px -3px;
}
</style>
{% endblock %}
{% block content %}
{% csrf_token %}
<h3 class="text-center">{{ article_obj.title }}</h3>
<div>
{{ article_obj.content|safe }} <!-- safe转义 -->
</div>
<div class="clearfix">
<div id="div_digg">
<div class="diggit action" onclick="votePost(16598898,'Digg')">
<span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
</div>
<div class="buryit action" onclick="votePost(16598898,'Bury')">
<span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips" style="color: red"></div>
</div>
</div>
<div>
<p>评论列表</p>
<ul class="comment_list list-group">
{% for comment in comment_list %}
<li class="list-group-item">
<div>
<a href=""># {{ forloop.counter }} 楼</a>
<span>{{ comment.create_time|date:"Y-m-d H:i" }}</span>
<a href=""><span>{{ comment.user.username }}</span></a>
<a href="" class="pull-right reply_btn" username="{{ comment.user.username }}" comment_pk="{{ comment.pk }}">回复</a>
</div>
{% if comment.parent_comment_id %}
<div class="pid_info well">
<p>{{ comment.parent_comment.user.username }}: {{ comment.parent_comment.content }}</p>
</div>
{% endif %}
<div style="margin-top: 10px">
<p>{{ comment.content }}</p>
</div>
</li>
{% endfor %}
</ul>
<p>发表评论</p>
<p>昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50"
value="{{ request.user.username }}"></p>
<p>评论内容:</p>
<textarea id="comment_content" cols="60" rows="7"></textarea>
<p>
<button class="btn btn-default comment_btn">提交评论</button>
</p>
</div>
{% endblock %}
{% block js %}
<script>
// 点赞请求
$("#div_digg .action").click(function () {
var is_up = $(this).hasClass("diggit");
var $obj = $(this).children("span");
$.ajax({
url: '/digg/',
type: 'post',
data: {
"csrfmiddlewaretoken": $('[name="csrfmiddlewaretoken"]').val(),
"is_up": is_up,
"article_id": "{{ article_obj.pk }}",
},
success: function (res) {
console.log(res);
if (res.static) {
var val = parseInt($obj.text());
$obj.text(val + 1);
} else {
var val = res.handled ? "您已经推荐过!" : "您已经反对过!";
$('#digg_tips').html(val);
setTimeout(function () {
$('#digg_tips').html("")
}, 1500)
}
}
})
});
// 评论请求
var pid = "";
$('.comment_btn').click(function () {
var content = $('#comment_content').val();
if (pid){
var index = content.indexOf("\n");
content = content.slice(index+1)
}
$.ajax({
url: '/comment/',
type: 'post',
data: {
"csrfmiddlewaretoken": $('[name="csrfmiddlewaretoken"]').val(),
"article_id": "{{ article_obj.pk }}",
"content": content,
"pid": pid,
},
success: function (res) {
console.log(res)
var create_time = res.create_time
var username = res.username
var content = res.content
var s = `
<li class="list-group-item">
<div>
<span>${create_time}</span>
<a href=""><span>${username}</span></a>
</div>
<div style="margin-top: 10px">
<p>${content}</p>
</div>
</li>
`;
$('ul.comment_list').append(s);
// 清空评论框
$('#comment_content').val("");
// 清空pid
pid = ""
}
})
});
// 回复按钮事件
$('.reply_btn').click(function () {
var val = "@"+$(this).attr("username")+'\n';
$('#comment_content').focus().text(val)
pid = $(this).attr("comment_pk");
});
</script>
{% endblock %}
编写inclusion_tag:
my_tags.py
from django import template
from django.db.models import Count
from blog import models
register = template.Library()
@register.inclusion_tag("classification.html")
def get_classification_style(username):
user_obj = models.UserInfo.objects.filter(username=username).first()
blog_obj = user_obj.blog
cate_list = models.Category.objects.filter(blog=blog_obj).values("pk").annotate(c=Count("article__title")).values_list("title", "c")
tag_list = models.Tag.objects.filter(blog=blog_obj).values("pk").annotate(c=Count("article")).values_list("title", "c")
date_list = models.Article.objects.filter(user=user_obj).extra(select={'y_m_date': 'date_format(create_time, "%%Y-%%m")'}).values("y_m_date").annotate(c=Count('nid')).values_list("y_m_date", "c")
return {"username": username, "user_obj": user_obj, "blog_obj": blog_obj, "cate_list": cate_list, "tag_list": tag_list, "date_list": date_list}
# 当代码执行完后,数据返回给classification.html模板进行渲染
classification.html
<div>
<div class="panel panel-warning">
<div class="panel-heading">我的标签</div>
<div class="panel-body">
{% for tag in tag_list %}
<p><a href="/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }} ({{ tag.1 }})</a></p>
{% endfor %}
</div>
</div>
<div class="panel panel-danger">
<div class="panel-heading">随笔分类</div>
<div class="panel-body">
{% for cate in cate_list %}
<p><a href="/{{ username }}/category/{{ cate.0 }}">{{ cate.0 }} ({{ cate.1 }})</a></p>
{% endfor %}
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading">随笔归档</div>
<div class="panel-body">
{% for date in date_list %}
<p><a href="/{{ username }}/archive/{{ date.0 }}">{{ date.0 }} ({{ date.1 }})</a></p>
{% endfor %}
</div>
</div>
</div>