仿bbs之侧边栏功能补充,点赞点踩功能,文章详细数据(内容)准备,文章评论功能部分讲解
- 侧边栏筛选功能
- 侧边栏封装
- 文章详细数据准备
- 点赞点踩样式搭建
- 文章点赞点踩功能
- 文章评论样式搭建
- 文章根评论功能
侧边栏筛选功能
1.先研究博客园三种情况下的筛选
分类筛选路由特性: 站点名称/category/数据主键值
标签筛选路由特性: 站点名称/tag/数据主键值
日期筛选路由特性: 站点名称/archive/文章年月
2.研究路由开设接口
多个路由使用相同的视图函数 因为个人站点的文章和侧边栏筛选的文章互为父子集
'''
# 侧边栏筛选功能接口
# path('<str:username>/category/<int:category_id>', views.site_func),
# path('<str:username>/tag/<int:tag_id>', views.site_func),
# path('<str:username>/archive/<str:yearAndmonth>', views.site_func),
# 上述三个路由可以合并成一个路由
re_path('^(?P<username>\w+)/(?P<condition>category|tag|archive)/(?P<params>.*?)/', views.site_func),
利用正则合并三个路由
'''
'''
后台判断筛选条件,进行再筛选,将再筛选的数据传到前端
'''
'''
前端绑定路由-根据路由的格式
'''



文章详情页搭建
1.路由的设计
站点名称\article\文章数据主键值
path('<str:username>/article/<int:article_id>/', views.article_detail_func),
def article_detail_func(request, username, article_id):
article_obj = models.Article.objects.filter(site__site_name=username).filter(pk=article_id).first()
site_obj = models.Site.objects.filter(site_name=username).first()
'''这里也可以添加健壮性校验 防止用户自己瞎点'''
if not article_obj:
return HttpResponse('你瞎点李奶奶呢')
return render(request, 'articleDetailPage.html', locals())
由于一份代码使用了两次,程序员的直觉告诉我不能这么做,于是我将代码写入一个自定义标签py文件
from django import template
from app01 import models
from django.db.models import Count
from django.db.models.functions import TruncMonth
register = template.Library()
@register.inclusion_tag('leftmenu.html', name='mymenu')
def index(username):
site_obj = models.Site.objects.filter(site_name=username).first()
category_queryset = models.Category.objects.filter(site=site_obj).annotate(article_num=Count('article__pk')).values(
'name', 'article_num', 'pk'
)
tag_queryset = models.Tag.objects.filter(site=site_obj).annotate(article_num=Count('article__pk')).values(
'name', 'article_num', 'pk'
)
date_queryset = models.Article.objects.filter(site=site_obj).annotate(month=TruncMonth('create_time')).values('month').annotate(
article_num=Count('pk')).values('month', 'article_num')
return locals()

新建html页面继承home并写入自定义标签

然后在文章标题的a标签内动态填写路由即可
/{{ article_obj.site.userinfo.username }}/article/{{ article_obj.pk }}/
文章详细数据准备
检查网页源码,找到cnblogs_post_body标签,复制html数据,然后填入文章详细内容,然后在前端展示页|safe
点赞点踩样式搭建
1.直接拷贝博客园样式即可 主要除了html还有css
'''
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/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;
}
</style>
'''
'''
html
<div class="clearfix">
<div id="div_digg">
<div class="diggit upordown">
<span class="diggnum" id="digg_count">{{ article_obj.up_num }}</span>
</div>
<div class="buryit upordown">
<span class="burynum" id="bury_count">{{ article_obj.down_num }}</span>
</div>
<div class="clear"></div>
<span style="color: red" id="d1"></span>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>
'''

2.针对路由匹配
含有动态匹配的路由很多时候可能会出现顶替的情况
这个时候我们可以将简单的路由放在前面 复杂的放在后面 甚至修改匹配策略

def up_or_down_func(request):
"""
1.校验用户是否登录
2.校验当前文章是否是当前用户自己的
3.校验当前文章是否已被当前用户点过
4.创建点赞点踩记录(不要忘记文章表中的优化字段 同步自增)
"""
back_dict = {'code': 10000, 'msg': ''}
if request.method == 'POST':
if request.user.is_authenticated:
is_up = request.POST.get('is_up')
article_pk = request.POST.get('article_pk')
article_obj = models.Article.objects.filter(pk=article_pk).first()
if not article_obj.site.userinfo == request.user:
is_click = models.UpAndDown.objects.filter(user=request.user, article=article_obj)
if not is_click:
is_up = json.loads(is_up)
if is_up:
models.Article.objects.filter(pk=article_pk).update(up_num=F('up_num') + 1)
back_dict['msg'] = '点赞成功'
else:
models.Article.objects.filter(pk=article_pk).update(down_num=F('down_num') + 1)
back_dict['msg'] = '点踩成功'
models.UpAndDown.objects.create(user=request.user, article=article_obj, is_up=is_up)
else:
back_dict['code'] = 10001
back_dict['msg'] = '您已经点过赞了'
else:
back_dict['code'] = 10002
back_dict['msg'] = '你不能给自己点赞'
else:
back_dict['code'] = 10003
back_dict['msg'] = '请先<a href="/login/">登录</a>'
return JsonResponse(back_dict)

文章点赞点踩样式
<div class="clearfix">
<div id="div_digg">
<div class="diggit upordown">
<span class="diggnum" id="digg_count">{{ article_obj.up_num }}</span>
</div>
<div class="buryit upordown">
<span class="burynum" id="bury_count">{{ article_obj.down_num }}</span>
</div>
<div class="clear"></div>
<span style="color: red" id="d1"></span>
<div class="diggword" id="digg_tips">
</div>
</div>
</div>
ajax请求:
'''
<script>
// 给点赞点踩图标绑定点击事件
$('.upordown').click(function () {
// 提前将当前点击对象存起来
let upOrDown = $(this);
let isUP = $(this).hasClass('diggit') // 判断标签是否含有某个class值 从而二选一区分赞和踩
// 发送ajax请求
$.ajax({
url: '/up_or_down/',
type: 'post',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'article_pk': {{ article_obj.pk }},
'is_up': isUP,
},
success:function (args) {
if (args.code === 10000){
{#upOrDown.find('span').text(Number(upOrDown.find('span').text()) + 1)#}
upOrDown.children().first().text(Number( upOrDown.children().first().text()) + 1)
}
$('#d1').html(args.msg)
}
})
})
</script>
'''


文章评论功能
1.前端样式搭建
{
<div class="comment-area">
<p><span class="glyphicon glyphicon-comment"></span>发表评论</p>
<textarea name="" id="" cols="30" rows="10" class="form-control"></textarea>
<button class="btn btn-primary">提交评论</button>
</div>
{

2.评论逻辑
先考虑根评论 之后再考虑子评论 不要乱!!!
3.根评论
点击提交评论按钮 发送ajax请求 携带必要的参数即可
path('comment/', views.comment_func),
'''
@login_required
def comment_func(request):
back_dict = {'code': 10000, 'msg': ''}
if request.method == 'POST':
article_pk = request.POST.get('article_pk')
content = request.POST.get('content')
# 文章内优化字段评论数自增1
models.Article.objects.filter(pk=article_pk).update(comment_num=F('comment_num') + 1)
# 在文章表内创建评论与文章主键值与用户主键值
models.Comment.objects.create(user=request.user, article_id=article_pk, content=content)
back_dict['msg'] = '评论成功'
return JsonResponse(back_dict)
'''
'''
// 给提交评论按钮绑定点击事件
$('#commentBtn').click(function () {
$.ajax({
url: '/comment/',
type: 'post',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'article_pk': '{{ article_obj.pk }}',
'content': $('#comment').val(),
},
success: function (args) {
}
})
})
'''
'''
{# 文章评论楼开始#}
<div class="comment_list">
<ul class="list-group">
{% for comment_obj in comment_list %}
{# span标签自增楼层#}
<li class="list-group-item">
<span><a href="#">#{{ forloop.counter }}楼</a></span>
<span>{{ comment_obj.comment_time|date:'Y-m-d H:i' }}</span>
<span><a href="/{{ comment_obj.user.username }}/">{{ comment_obj.user.username }}</a></span>
<p>
{{ comment_obj.content }}
</p>
</li>
{% endfor %}
</ul>
</div>
{# 文章评论楼结束#}
'''
