# url设计 /username/article/1 # 先验证url是否会被其余url顶替 # 文章详情页和我的站点基本一致 因此用模版继承 # 侧边栏的渲染须要传输数据才能渲染 而且该侧边栏在不少页面都须要使用 1.哪一个地方用就拷贝须要的代码(不推荐 有点繁琐) 2.将侧边栏制做成inclusion_tag """ 步骤 1.在应用下建立一个名字必须叫templatetags文件夹 2.在该文件夹内建立一个任意名称的py文件 3.在该py文件内先固定写两行代码 from django import template register = template.Library() # 自定义过滤器 # 自定义标签 # 自定义inclusion_tag """ # 自定义inclusion_tag @register.inclusion_tag('left_menu.html') def left_menu(username): # 构造侧边栏须要的数据 user_obj = models.UserInfo.objects.filter(username=username).first() blog = user_obj.blog # 1 查询当前用户全部的分类及分类下的文章数 category_list = models.Category.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list( 'name', 'count_num', 'pk') # print(category_list) # <QuerySet [('jason的分类一', 2), ('jason的分类二', 1), ('jason的分类三', 1)]> # 2 查询当前用户全部的标签及标签下的文章数 tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list('name', 'count_num', 'pk') # print(tag_list) # <QuerySet [('tank的标签一', 1), ('tank的标签二', 1), ('tank的标签三', 2)]> # 3 按照年月统计全部的文章 date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values( 'month').annotate(count_num=Count('pk')).values_list('month', 'count_num') # print(date_list) return locals()
""" 浏览器上你看到的花里胡哨的页面,内部都是HTML(前端)代码 那如今咱们的文章内容应该写什么??? >>> html代码 如何拷贝文章 copy outerhtml 1.拷贝文章 2.拷贝点赞点踩 1.拷贝前端点赞点踩图标 只拷了html 2.css也要拷贝 因为有图片防盗链的问题 因此将图片直接下载到本地 课下思考: 前端如何区分用户是点了赞仍是点了踩 1.给标签各自绑定一个事件 两个标签对应的代码其实基本同样,仅仅是是否点赞点踩这一个参数不同而已 2.二合一 给两个标签绑定一个事件 // 给全部的action类绑定事件 $('.action').click(function () { alert($(this).hasClass('diggit')) }) 因为点赞点踩内部有必定的业务逻辑,因此后端单独开设视图函数处理 """ # 我的建议:写代码先把全部正确的逻辑写完再去考虑错误的逻辑 不要试图二者兼得 import json from django.db.models import F def up_or_down(request): """ 1.校验用户是否登录 2.判断当前文章是不是当前用户本身写的(本身不能点本身的文章) 3.当前用户是否已经给当前文章点过了 4.操做数据库了 :param request: :return: """ if request.is_ajax(): back_dic = {'code':1000,'msg':''} # 1 先判断当前用户是否登录 if request.user.is_authenticated(): article_id = request.POST.get('article_id') is_up = request.POST.get('is_up') # print(is_up,type(is_up)) # true <class 'str'> is_up = json.loads(is_up) # 记得转换 # print(is_up, type(is_up)) # True <class 'bool'> # 2 判断当前文章是不是当前用户本身写的 根据文章id查询文章对象 根据文章对象查做者 根request.user比对 article_obj = models.Article.objects.filter(pk=article_id).first() if not article_obj.blog.userinfo == request.user: # 3 校验当前用户是否已经点了 哪一个地方记录了用户到底点没点 is_click = models.UpAndDown.objects.filter(user=request.user,article=article_obj) if not is_click: # 4 操做数据库 记录数据 要同步操做普通字段 # 判断当前用户点了赞仍是踩 从而决定给哪一个字段加一 if is_up: # 给点赞数加一 models.Article.objects.filter(pk=article_id).update(up_num = F('up_num') + 1) back_dic['msg'] = '点同意功' else: # 给点踩数加一 models.Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1) back_dic['msg'] = '点踩成功' # 操做点赞点踩表 models.UpAndDown.objects.create(user=request.user,article=article_obj,is_up=is_up) else: back_dic['code'] = 1001 back_dic['msg'] = '你已经点过了,不能再点了' # 这里你能够作的更加的详细 提示用户到底点了赞仍是点了踩 else: back_dic['code'] = 1002 back_dic['msg'] = '你个臭不要脸的!' else: back_dic['code'] = 1003 back_dic['msg'] = '请先<a href="/login/">登录</a>' return JsonResponse(back_dic) <script> // 给全部的action类绑定事件 $('.action').click(function () { {#alert($(this).hasClass('diggit'))#} let isUp = $(this).hasClass('diggit'); let $div = $(this); // 朝后端发送ajax请求 $.ajax({ url:'/up_or_down/', type:'post', data:{ 'article_id':'{{ article_obj.pk }}', 'is_up':isUp, 'csrfmiddlewaretoken':'{{ csrf_token }}' }, success:function (args) { if(args.code == 1000){ $('#digg_tips').text(args.msg) // 将前端的数字加一 // 先获取到以前的数字 let oldNum = $div.children().text(); // 文本 是字符类型 // 易错点 $div.children().text(Number(oldNum) + 1) // 字符串拼接了 1+1 = 11 11 + 1 = 111 }else{ $('#digg_tips').html(args.msg) } } }) }) </script>
""" 咱们先写根评论 再写子评论 点击评论按钮须要将评论框里面的内容清空 根评论有两步渲染方式 1.DOM临时渲染 2.页面刷新render渲染 子评论 点击回复按钮发生了几件事 1.评论框自动聚焦 2.将回复按钮所在的那一行评论人的姓名 @username 3.评论框内部自动换行 根评论子评论都是点击一个按钮朝后端提交数据的 parent_id 根评论子评论区别在哪? parent_id """