python自动化开发-[第二十二天]-bbs多级评论、点赞、上传文件

时间:2023-03-09 08:49:53
python自动化开发-[第二十二天]-bbs多级评论、点赞、上传文件

今日概要:

  1、related_name和related_query_name的区别

  2、through_fields的用途

  3、django的事务提交

  4、点赞的动画效果

  5、多级评论的原理

  6、上传文件

  7、request.post用法

  8、如果保留原来的页面

一、related_name和related_query_name的区别

  related_name,用于定义反向关联时候,使用的字段名称

  related_query_name 用于反向查询related_query_name + _set进行查询

  例子:  

class A:
title = models.CharField()
obj = models.A.objects.get(id=1)
obj.b_set.all()
obj.xxxxxx_set.all() # related_query_name='xxxxxx'
obj.uuuu.all() # related_name='uuuu' obj.x
obj.u class B:
xx ..xx
fk1 = models.ForignKey(related_name='x')
fk2 = models.ManyToMany(related_name='u') models.B.objects.filter(fk__title='xx')

二、through_fields的用途

  through_fields = (在关系表中与当前表建立FK关系的字段名称,在关系表中与目标表建立的FK关系字段名称)

  例子:

likes = models.ManyToManyField(to='UserInfo',through="Like",through_fields=('new','user')) #当前表是new表

三、django的事务提交

  保持两条sql的同时正确才进行插入动作

	from django.db import transaction
with transaction.atomic():
  models.Like.objects.create(nnew_id=new_id,uuser_id=uid)
  models.News.objects.filter(id=new_id).update(like_count=F('like_count') + 1)
response.code = 999

   返回值封装:

class BaseResponse(object):
def __init__(self):
self.status = False
self.data = None
self.msg = None def get_dict(self):
return self.__dict__ class LikeResponse(BaseResponse):
def __init__(self):
self.code = 0
super(LikeResponse,self).__init__() json.dumps(对象.__dict__)
json.dumps(对象.get_dict())

四、点赞的动画效果

  *在ajax中操作回调函数中的 $(this)已经不是原来的$(this) 

  解决方法:通过一个变量来传递

  应用内容:css中的position:fixed,absolute,relative setInterval:定时器

js代码:  

$(function () {
bindLikeEvent();
}); function bindLikeEvent() {
$('.new-like').click(function () {
// 获取当前新闻ID
var newId = $(this).attr('new-id');
var $this = $(this);
$.ajax({
url: '/do_like.html',
type: "POST",
data: {'newId': newId},
dataType: 'JSON',
success:function (arg) {
if(arg.status){
var origin = $this.text();
var count = parseInt(origin);
if(arg.code == 666){
$this.text(count - 1 );
showLikeCount($this,'-1'); }else if(arg.code == 999){
$this.text(count + 1 );
showLikeCount($this,'+1'); }
}else{
alert(arg.msg);
}
} })
})
} function showLikeCount($this,text) {
var fontSize = 5;
var top = 0;
var right = 0;
var opacity = 1;
var tag = document.createElement('span');
tag.innerText = text;
tag.style.position = "absolute";
tag.style.fontSize = fontSize + "px";
tag.style.top = top + "px";
tag.style.right = right + "px";
tag.opacity = opacity; $this.after(tag); var obj = setInterval(function () {
fontSize += 5 ;
top -= 5;
right -= 5 ;
opacity -= 0.1 ;
tag.style.fontSize = fontSize + "px";
tag.style.top = top + "px";
tag.style.right = right + "px";
tag.style.opacity = opacity;
if (opacity <= 0 ){
clearInterval(obj);
tag.remove()
}
},100) }
</script>

五、多级评论的原理

  知识点:字典和列表,通过引用赋值,一个修改全部都改变

      递归

  

#!/usr/bin/python
# -*- coding:utf-8 -*- def build_comment_data(li):
dic = {} #定义一个空字典dic
for item in li:
item['children'] = [] #列表字典中新增一个key叫children,value为空
dic[item['id']] = item #给空字典dic赋值 key是列表中字典中的id,value是列表字典 result = [] #定义一个空列表,存最后的结果 for item in li: #item是li列表中的每一行字典
pid = item['parent_id'] #pid是取每一行字典中parent_id的值
if pid: #如果每一行字典中parent_id有值
dic[pid]['children'].append(item) #则找到字典中pid的那一行,把item加到children里
else:
result.append(item) #否则把parent_id没有值的加到result列表中
# for i in result:
# print(i)
return result def build_comment_tree(com_list1):
tpl = """
<div class="item>
<div class="title">{0}:{1}</div>
<div class="body>{2}</div>
</div>
"""
#这里的{0}{1}{2}都是占位符 html=""
# print(com_list1)
# for i in com_list1:
# print(i)
for item in com_list1:
if not item['children']: #如果字典中没有children
html += tpl.format(item['user'],item['content'],"") #format给占位符传值,第三个值为空
else:
html += tpl.format(item['user'], item['content'], build_comment_tree(item['children']))
#如果有子children则把build_comment_tree函数自己再执行一遍,把孩子传进去(孩子也是一个完整的字典)
return html def comment_list():
li = [
{'id': 1, 'user': '银秋良', 'content': '灌我鸟事', 'parent_id': None},
{'id': 2, 'user': '银秋良', 'content': '管我鸟事', 'parent_id': None},
{'id': 3, 'user': '型谱', 'content': '你个文盲', 'parent_id': 1},
{'id': 4, 'user': '详解', 'content': '好羡慕你们这些没脸的人呀', 'parent_id': 2},
{'id': 5, 'user': '银秋良', 'content': '你是流氓', 'parent_id': 3},
{'id': 6, 'user': '银秋良', 'content': '你冷库无情', 'parent_id': 5},
{'id': 7, 'user': '银秋良', 'content': '你才冷酷无情', 'parent_id': 4},
{'id': 8, 'user': '银秋良', 'content': '你无理取闹', 'parent_id': 4},
]
com_list = build_comment_data(li) html = build_comment_tree(com_list)
print(html) if __name__ == '__main__':
comment_list()

  知识回顾:  

l = [1,2,4,5,6] #迭代器
for i in l: #迭代器对象
# 迭代器出现报错 l.__iter__() next()取到空的情况,迭代器对象不会 for j in l:
print(i)

   引用类型应用:

li = [
{'user':'xxx','pwd':'xxx','id':1,"children":[],'parent_id':None},
{'user':'xxx','pwd':'xxx','id':2,"children":[],'parent_id':None},
{'user':'xxx','pwd':'xxx','id':3,"children":[],'parent_id':1},
{'user':'xxx','pwd':'xxx','id':4,"children":[],'parent_id':2},
{'user':'xxx','pwd':'xxx','id':5,"children":[],'parent_id':1},
{'user':'xxx','pwd':'xxx','id':6,"children":[],'parent_id':3},
]
#结果:
# result = [
# {'user':'xxx','pwd':'xxx','id':1,"children":[{'user':'xxx','pwd':'xxx','id':3,"children":[ {'user':'xxx','pwd':'xxx','id':6,"children":[],'parent_id':3},],'parent_id':1},{'user':'xxx','pwd':'xxx','id':5,"children":[],'parent_id':1},],'parent_id':None},
# {'user':'xxx','pwd':'xxx','id':2,"children":[{'user':'xxx','pwd':'xxx','id':4,"children":[],'parent_id':2},],'parent_id':None},
# ] dict = {}
for i in li:
dict[i['id']] = i a = []
for k,v in dict.items():
if v['parent_id']:
dict[v['parent_id']]["children"].append(v)
else:
a.append(v) print(a)

  javascript实现多级评论:

  

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.hide {
display: none;
}
.body{
margin-left: 30px;
} </style>
</head>
<body>
<h1>多级评论</h1>
<a id="a1" href="#" onclick="myClick()">点我</a>
{# {{ comment_list | safe }}#} <script src="/static/jquery-3.2.1.js"></script>
<script> function my_iter(arg) {
var h = "";
$.each(arg,function (k,v) {
if (v['children']){
h += '<div class="item"><div class="title">' + v['user'] + ':' + v['content'] + '</div> <div class="body">' + my_iter(v['children']) + '</div></div>'
}else{
h += '<div class="item"><div class="title">' + v['user'] + ':' + v['content'] + '</div><div class="body"></div></div>'
}
});
return h
} $(function () {
$('body').on('click',".title",function () {
if ($(this).next().hasClass('hide')){
$(this).next().removeClass('hide')
}else{
$(this).next().addClass('hide')
}
})
});
function myClick() {
$.ajax({
url:'/comment',
type:"POST",
data:"1",
dataType:"JSON",
success:function (arg) {
console.log(my_iter(arg));
$('#a1').after(my_iter(arg))
}
})
} </script>
</body>
</html>

六、上传文件  

  - 基于FormData
  - 缺点,兼容性不好
  - 优点,Ajax直接发送

  - 伪Ajax,兼容性更好
  - iframe,天生局部刷新
  - form,天生整个页面刷新

七、request.post用法

- 如何通过python代码发送post数据?
URL: http://127.0.0.1:8003/asset.html 客户端:
import requests
# response = requests.get('http://127.0.0.1:8003/asset.html')
# print(response.text)
data_dict = {
'k1':'v1',
'k2':'v2'
}
# content-type: application/x-www-form-urlencoded
# response = requests.post('http://127.0.0.1:8003/asset.html',data=data_dict)
# print(response.text) # content-type: appcation/json
response = requests.post('http://127.0.0.1:8003/asset.html',json=data_dict)
print(response.text) 服务端Django:
from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_exempt
def asset(request):
if request.method == "GET":
return HttpResponse('收到:GET')
else:
print(request.POST)
print(request.body)
return HttpResponse('收到:POST')

八、如果保留原来的页面 

request.GET
from django.http.request import QueryDict
要点:
POST,不要写action

例子:  

def host_list(request):
print(request.GET,type(request.GET))
# request.GET._mutable = True obj = QueryDict(mutable=True)
obj['_zhaofengfeng'] = request.GET.urlencode() # page=10&id=1
url_param = obj.urlencode() hosts = ['c1.com','c2.com','c3.com']
return render(request,'host_list.html',{'hosts':hosts,'url_param':url_param}) def add_host(request):
if request.method == "GET":
return render(request,'add.html')
else:
url_params = request.GET.get('_zhaofengfeng')
host = request.POST.get('hostname')
url ="/host_list.html?"+url_params
return redirect(url)