django高级之点赞、文章评论及上传文件
目录:
- 点赞
- 文章评论
- 上传文件
- 保留页面条件
一、点赞
1、所用技术:
- django model F查询
- js应用:$(function () {}); 为文件加载完成执行ready() 方法。等同于on时间,多实例,使用。
定时器方法:setInterval(方法,间隔多长时间(毫秒)执行一次)
var obj = setInterval(function () {
if(xxx <= 0){
clearInterval(obj); //结束执行
},100);
ps.setTimeout(表达式,延时时间)在执行时,是在载入后延迟指定时间后,去执行一次表达式,记住,次数是一次
- css应用:
position属性
值 | 描述 |
---|---|
absolute |
生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 |
fixed |
生成绝对定位的元素,相对于浏览器窗口进行定位。 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 |
relative |
生成相对定位的元素,相对于其正常位置进行定位。 因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。 |
static | 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。 |
inherit | 规定应该从父元素继承 position 属性的值。 |
- 在Ajax操作时候,回调函数中的 $(this)已经不是原来的$(this)。需在外层函数声明。
2、应用代码:
前端:
1 <div> 2 <div>{{ row.title }}</div> 3 <div>{{ row.user.username }} 评论:{{ row.comment_count }} 4 <!--使用相对定位--> 5 <div style="display: inline-block;position: relative;"> 6 赞:<a class="new-like" new-id="{{ row.id }}">{{ row.like_count }}</a> 7 </div> 8 </div> 9 </div> 10 <script src="/static/jquery-3.2.1.js"></script> 11 <script> 12 $(function () { 13 bindLikeEvent(); 14 }); 15 16 function bindLikeEvent() { 17 $('.new-like').click(function () { 18 // 获取当前新闻ID 19 var newId = $(this).attr('new-id'); 20 var $this = $(this); 21 $.ajax({ 22 url: '/do_like.html', 23 type: "POST", 24 data: {'newId': newId}, 25 dataType: 'JSON', 26 success:function (arg) { 27 if(arg.status){ 28 var origin = $this.text(); 29 var count = parseInt(origin); 30 if(arg.code == 666){ 31 $this.text(count - 1 ); 32 showLikeCount($this,'-1'); 33 34 }else if(arg.code == 999){ 35 $this.text(count + 1 ); 36 showLikeCount($this,'+1'); 37 38 } 39 }else{ 40 alert(arg.msg); 41 } 42 } 43 44 }) 45 }) 46 } 47 48 function showLikeCount($this,text) { 49 var fontSize = 5; 50 var top = 0; 51 var right = 0; 52 var opacity = 1; 53 54 var tag = document.createElement('span'); 55 // var tag = document.getElementById() 56 tag.innerText = text; 57 tag.style.position = "absolute"; 58 // 默认大小 59 tag.style.fontSize = fontSize + "px"; 60 tag.style.top = top + 'px'; 61 tag.style.right = right + 'px'; 62 tag.style.opacity = opacity; 63 $this.after(tag); 64 65 // 定时器,没0.5s执行一次 66 var obj = setInterval(function () { 67 fontSize += 5; 68 top -= 5; 69 right -= 5; 70 opacity -= 0.1; 71 72 tag.style.fontSize = fontSize + "px"; 73 tag.style.top = top + 'px'; 74 tag.style.right = right + 'px'; 75 tag.style.opacity = opacity; 76 if(opacity <= 0){ 77 clearInterval(obj); 78 tag.remove(); 79 } 80 },100); 81 82 } 83 </script>
后端:
1 import json 2 from django.db.models import F 3 from django.db import transaction 4 from utils.response import LikeResponse 5 6 def do_like(request): 7 """ 8 点赞 9 :param request: 10 :return: 11 """ 12 response = LikeResponse() 13 try: 14 new_id = request.POST.get('newId') 15 # 当前登录用户ID 16 # uid = request.session.get('uid') 17 uid = 1 18 19 exist_like = models.Like.objects.filter(nnew_id=new_id,uuser_id=uid).count() 20 with transaction.atomic(): 21 if exist_like: 22 models.Like.objects.filter(nnew_id=new_id, uuser_id=uid).delete() 23 models.News.objects.filter(id=new_id).update(like_count=F('like_count') - 1) 24 response.code = 666 25 else: 26 models.Like.objects.create(nnew_id=new_id,uuser_id=uid) 27 models.News.objects.filter(id=new_id).update(like_count=F('like_count') + 1) 28 response.code = 999 29 except Exception as e: 30 response.msg = str(e) 31 else: 32 response.status = True 33 return HttpResponse(json.dumps(response.get_dict()))
ps.response实例化
1 class BaseResponse(object): 2 def __init__(self): 3 self.status = False 4 self.data = None 5 self.msg = None 6 7 def get_dict(self): 8 return self.__dict__ 9 10 11 class LikeResponse(BaseResponse): 12 def __init__(self): 13 self.code = 0 14 super(LikeResponse,self).__init__() 15 16 # obj = LikeResponse() 17 # print(obj.__dict__)
二、文章评论
1、所用技术
- python:
字典,列表,通过引用赋值,一个修改全部都改的特性
递归取值
2、应用
前端:
1 <h1>评论</h1> 2 {{ comment_html|safe }}
后端:
1 def build_comment_data(li): 2 dic = {} 3 for item in li: 4 item['children'] = [] 5 dic[item['id']] = item 6 7 result = [] 8 for item in li: 9 pid = item['parent_id'] 10 if pid: 11 dic[pid]['children'].append(item) 12 else: 13 result.append(item) 14 15 return result 16 17 def build_comment_tree(com_list): 18 """ 19 {'user': '银秋良1', 'children': [],content:'xxx'], 20 {'user': '银秋良2', 'children': [{'user': '型谱', 'children': [{'user': '银秋良', 'children': [], 'parent_id': 3, 'content': '你是流氓', 'id': 5}], 'parent_id': 1, 'content': '你个文盲', 'id': 3}], 'parent_id': None, 'content': '灌我鸟事', 'id': 1} 21 {'user': '银秋良3', 'children': [{'user': '详解', 'children': [], 'parent_id': 2, 'content': '好羡慕你们这些没脸的人呀', 'id': 4}], 'parent_id': None, 'content': '管我鸟事', 'id': 2} 22 23 [ 24 {'user': '银秋良', 'children': [], 'parent_id': 3, 'content': '你是流氓', 'id': 5} 25 ] 26 27 """ 28 tpl = """ 29 <div class="item"> 30 <div class="title">{0}:{1}</div> 31 <div class="body">{2}</div> 32 </div> 33 """ 34 html = "" 35 for item in com_list: 36 if not item['children']: 37 html +=tpl.format(item['user'],item['content'],"") 38 else: 39 html +=tpl.format(item['user'], item['content'], build_comment_tree(item['children'])) 40 return html 41 42 def comment_list(request): 43 """ 44 获取多级评论列表 45 :param request: 46 :return: 47 """ 48 li = [ 49 {'id': 1, 'user': '银秋良', 'content': '灌我鸟事', 'parent_id': None}, 50 {'id': 2, 'user': '银秋良', 'content': '管我鸟事', 'parent_id': None}, 51 {'id': 3, 'user': '型谱', 'content': '你个文盲', 'parent_id': 1}, 52 {'id': 4, 'user': '详解', 'content': '好羡慕你们这些没脸的人呀', 'parent_id': 2}, 53 {'id': 5, 'user': '银秋良', 'content': '你是流氓', 'parent_id': 3}, 54 {'id': 6, 'user': '银秋良', 'content': '你冷库无情', 'parent_id': 5}, 55 {'id': 7, 'user': '银秋良', 'content': '你才冷酷无情', 'parent_id': 4}, 56 {'id': 8, 'user': '银秋良', 'content': '你无理取闹', 'parent_id': 4}, 57 ] 58 com_list = build_comment_data(li) 59 """ 60 {'user': '银秋良', 'children': [{'user': '型谱', 'children': [{'user': '银秋良', 'children': [], 'parent_id': 3, 'content': '你是流氓', 'id': 5}], 'parent_id': 1, 'content': '你个文盲', 'id': 3}], 'parent_id': None, 'content': '灌我鸟事', 'id': 1} 61 {'user': '银秋良', 'children': [{'user': '详解', 'children': [], 'parent_id': 2, 'content': '好羡慕你们这些没脸的人呀', 'id': 4}], 'parent_id': None, 'content': '管我鸟事', 'id': 2} 62 """ 63 64 html = build_comment_tree(com_list) 65 66 return render(request,'comment_list.html',{'comment_html':html}) 67 68 def fetch_comment(request): 69 li = [ 70 {'id': 1, 'user': '银秋良', 'content': '灌我鸟事', 'parent_id': None}, 71 {'id': 2, 'user': '银秋良', 'content': '管我鸟事', 'parent_id': None}, 72 {'id': 3, 'user': '型谱', 'content': '你个文盲', 'parent_id': 1}, 73 {'id': 4, 'user': '详解', 'content': '好羡慕你们这些没脸的人呀', 'parent_id': 2}, 74 {'id': 5, 'user': '银秋良', 'content': '你是流氓', 'parent_id': 3}, 75 {'id': 6, 'user': '银秋良', 'content': '你冷库无情', 'parent_id': 5}, 76 {'id': 7, 'user': '银秋良', 'content': '你才冷酷无情', 'parent_id': 4}, 77 {'id': 8, 'user': '银秋良', 'content': '你无理取闹', 'parent_id': 4}, 78 ] 79 com_list = build_comment_data(li) 80 # 第一种选择 81 html = build_comment_tree(com_list) 82 return HttpResponse(html) 83 # 第二种选择,前端递归去生成 84 # return HttpResponse(json.dumps(com_list))
ps.使用方式:
返回给前端JavaScrip,由前端递归渲染。本例为服务器直接渲染返回
三、上传文件
1、所使用技术:
- js:
- 基于FormData
- 缺点,兼容性不好
- 优点,Ajax直接发送
- 伪Ajax,兼容性更好
- iframe,天生局部刷新
- form,天生整个页面刷新
2、应用:
前端:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <input type="text" placeholder="默认值看看刷新之后在不在" /> 9 <form method="POST" target="xxxxxx" action="/upload_img2/" enctype="multipart/form-data"> 10 {% csrf_token %} 11 <input type="text" name="user" /> 12 <a style="width: 60px;height: 30px;background-color: darkslateblue;color: white;display: inline-block;position: relative;"> 13 上传 14 <input type="file" name="avatar" style="opacity: 0;position: absolute;left: 0;top:0;right: 0;bottom: 0;" /> 15 </a> 16 <input type="submit" value="提交" /> 17 </form> 18 <iframe id="ifm" name="xxxxxx" onload="successCallback(this);" style="display: none;" ></iframe> 19 <div id="imgList"></div> 20 <script src="/static/jquery-3.2.1.js"></script> 21 <script> 22 function successCallback(ths){ 23 var response = ths.contentWindow.document.body.innerHTML; 24 response = JSON.parse(response); 25 console.log(response); 26 var img = document.createElement('img'); 27 img.src = "/" + response.data; 28 29 $('#imgList').append(img); 30 31 } 32 </script> 33 34 </body> 35 </html>
后端:
1 def upload_img2(request): 2 response = BaseResponse() 3 try: 4 user = request.POST.get('user') 5 obj = request.FILES.get('avatar') 6 img_path = os.path.join('static', 'img', obj.name) 7 with open(img_path,mode='wb') as f: 8 for chunk in obj.chunks(): 9 f.write(chunk) 10 except Exception as e: 11 response.msg = str(e) 12 else: 13 response.status = True 14 response.data = img_path 15 return HttpResponse(json.dumps(response.get_dict()))
四、保留页面条件
1、所用技术:
django request.GET.urlencode() 获取url.get方法
django from django.http.request import QueryDict 导入QueryDict方法
ps.POST,不要写action
2、应用:
前端:
list
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <a href="/add_host.html?{{ url_param }}">添加</a> 9 <ul> 10 {% for item in hosts %} 11 <li>{{ item }}</li> 12 {% endfor %} 13 </ul> 14 </body> 15 </html>
add
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form method="POST"> 9 {% csrf_token %} 10 <input type="text" name="hostname" /> 11 <input type="submit" value="提交" /> 12 </form> 13 </body> 14 </html>
后端:
1 from django.http.request import QueryDict 2 def host_list(request): 3 print(request.GET,type(request.GET)) 4 # request.GET._mutable = True 5 6 obj = QueryDict(mutable=True) 7 obj['_zhaofengfeng'] = request.GET.urlencode() # page=10&id=1 8 url_param = obj.urlencode() 9 10 hosts = ['c1.com','c2.com','c3.com'] 11 return render(request,'host_list.html',{'hosts':hosts,'url_param':url_param}) 12 13 def add_host(request): 14 if request.method == "GET": 15 return render(request,'add.html') 16 else: 17 url_params = request.GET.get('_zhaofengfeng') 18 host = request.POST.get('hostname') 19 url ="/host_list.html?"+url_params 20 return redirect(url)