Python全栈知识点
知识点(持续更新) 1 ModelSerializer里有个属性可以设置跨表的深度 depth = 1 # 0-10 2 获取choice中文名(字段有select属性的) obj.get_level_display() 3 vue中重定向url(通过push改变url) this.$router.push({name:'detail', params:{id:id}}) !!!注意,与取query的区别 this.$route.query 以及取id(路由的id): this.$route.id 4 vue中通过click方法实现重新加载页面,上一个知识点的补充 5 关于ajax 如果是复杂请求: option请求先进行预检,通过之后才可以发post请求 6 随机字符串 import uuid # 根据网卡和时间生成的随机字符串 v = uuid.uuid4() str(v) 7 关于django的orm --> 有就更新,没有就创建 models.UserToken.objects.update_or_create(user=user, defaults={'token': uid}) 8 axios里 , params:{ token: ... } // 数据会拼到url上发给后端 后端取值:request.query_params.get('token') 9 认证的返回值 1 成功 2 失败 3 None(匿名用户) 10 部署django项目的时候 setting.py --> ALLOWED_HOST = ['*', ] # 允许所有主机访问 11 某个函数免除csrf_token验证 from django.views.decorations.csrf import csrf_exempt @csrf_exempt def update_order(request): ... 12 为什么要有foreignkey 1 节省硬盘 (所以数据量比较大时,为了提高查询速度,允许出现数据冗余,不会使用fk,) 2 做约束 3 缺点: 做查询时会比较慢,因为涉及到链表 13 根据字符串导入模块,并使用反射找到模块中的类 import importlib path = 'auth.csrf.CORS' module_path, class_name = path.rsplit('.', maxsplit=1) # 根据字符串导入模块 m = importlib.import_module(module_path) print(m, type(m)) cls = getattr(m, class_name) obj = cls() obj.process_request() 14 一些关于接口的知识点 1 特殊异常捕获 2 文件名除类以外, 一般小写+下划线 3 封装相应对象 4 简单逻辑先处理 5 简单接口时, 可以使用rest framework封装的功能 6 接口如何编写? 根据业务来编写: 1 返回所有: 2 返回多个接口 7 from django.db.models import F, Q # F 更新数据库字段 # Q 构造复杂条件 8 事务 (原子型操作要加上事务) 15 orm选择连接数据库 objs = models.User.objects.all().using('db1') 16 Q查询的两种方式 # 方式一: # Q(nid__gt=10) # Q(nid=8) | Q(nid__gt=10) # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') # 方式二: # con = Q() # q1 = Q() # q1.connector = 'OR' # q1.children.append(('id', 1)) # q1.children.append(('id', 10)) # q1.children.append(('id', 9)) # q2 = Q() # q2.connector = 'OR' # q2.children.append(('c1', 1)) # q2.children.append(('c1', 10)) # q2.children.append(('c1', 9)) # con.add(q1, 'AND') # con.add(q2, 'AND') 17 dir(cls) 可以获取类的所有静态属性 18 通过路径导入模块 importlib 19 完美的装饰器 import functools def auth(func): @functools.wraps(func) # 保留原函数的元信息 def inner(*args, **kwargs): pass 20 mysql数据库 - 引擎 - innodb 支持事务 支持行锁表锁 查询慢 - myisam 不支持十五 支持表锁 查询快 - 数据库锁 - 原生: 加锁: begin; # 开始事务 select * from db1 for update; 解锁: commit; - pymysql cursor.execute('select * from tb for update') - django with trancation.automic(): models.User.objects.all().for_update() 22 栈 后进先出(弹夹) class Stack(object): def push(self, item): pass class pop(self): pass 23 队列 先进先出 结构同上 24 http协议的refer头 refer头: 上一次请求地址, 可以用于做防盗链 25 字典update a = {'a': 1, 'b': 'hello', 'c': 222} b = {'a': 222, 'd': '99999'} a.update(b) # 会将b更新到a中 print(a) 26 flask开启多线程 app.run(host='192.168.23.5', threaded=True) 27 轮询/长轮询 轮询: 客户端没2秒钟向服务端发一个请求 思路: 1 客户端写一个定时器, 每2秒给服务器发一个ajax请求, 2 服务端给客户端返回最新的数据 3 客户端更新数据 长轮询: 服务端hang住客户端的请求, 30秒后再给客户端返回 (优点: 实时,在线,兼容性好) 思路: 1 为每一个用户创建一个队列, 2 用户来服务端获取数据时通过: q.get(timeout=30) - 队列有数据了则直接返回数据给前端 (什么时候才有数据: 3 更新数据的请求来了, q.put(data) ) - 队列没有数据给前端返回None # 以实时投票做比喻 # app.py from flask import Flask, render_template, request, jsonify, session import queue import uuid app = Flask(__name__) app.secret_key = 'sdlfs' USERS = { '1': {'name': '贝贝', 'count': 1}, '2': {'name': '小东北', 'count': 0}, '3': {'name': '何伟明', 'count': 0}, } QUEUE_DICT = { } @app.route('/index') def index(): user_uuid = str(uuid.uuid4()) QUEUE_DICT[user_uuid] = queue.Queue() # 1 每个用户来了都实例化一个队列 session['current_user_uuid'] = user_uuid # 将每个用户的队列的唯一标示写进cookie return render_template('user_list.html', users=USERS) @app.route('/vote', methods=['POST']) def vote(): uid = request.form.get('uid') # 获取每个用户队列的唯一标示 USERS[uid]['count'] += 1 for item in QUEUE_DICT.values(): # /4 往每一个用户的队列put更新后的值 item.put(USERS) return '投票成功' @app.route('/get_vote') def get_vote(): user_uuid = session['current_user_uuid'] q = QUEUE_DICT[user_uuid] ret = {'status': True, 'data': None} try: users = q.get(timeout=5) # 3 去队列里取值, hang住5秒等待数据 ret['data'] = users # /5 一有数据就返回 except queue.Empty: ret['status'] = False # 超时的时候 4/5 这两步骤走这里 return jsonify(ret) if __name__ == '__main__': app.run() # user_list.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> <style> li { cursor: pointer; } </style> </head> <body> <ul id="user_list"> {% for k,v in users.items() %} <li uid="{{k}}">{{v.name}}({{v.count}})</li> {% endfor %} </ul> <script src="https://cdn.bootcss.com/jquery/3.3.0/jquery.min.js"></script> <script> // 获取投票信息 function get_vote() { $.ajax({ url: '/get_vote', type: 'get', success: function (arg) { if (arg.status) { // 1 清空ul标签 $('#user_list').empty(); // 2 生成ul标签 $.each(arg.data, function (k, v) { var li = document.createElement('li'); li.setAttribute('uid', k); li.innerText = v.name + '(' + v.count + ')'; $('#user_list').append(li); }); } get_vote(); // 7 递归去获取投票信息 } }) } $(function () { // dom加载完就执行 $('#user_list').on('click', ' li', function () { var uid = $(this).attr('uid'); $.ajax({ url: '/vote', type: 'post', data: {uid: uid}, success: function (arg) { console.log(arg); } }) }); get_vote(); // 2 去获取投票信息 }); // t = setInterval(get_vote, 3000); </script> </body> </html> 28 查看Response有什么方法? 去源码的地方看 from scrapy.http.response.html import HtmlResponse 29 django中 request.POST 只能取到格式是 encodeform格式的数据 request.body 必定可以取到前端发来的数据 30 怎么判断服务端要什么格式的数据? chrome调试工具-->network里看 chrome-> Form Data: # Firefox为表单 phone=861513125555&password=12312312312&oneMonth=1 reqeusts.post( url=url, data={ phone:123123123123, password:asdfasdf } ) Request Payload: # Firefox为json {"BaseRequest":{"Uin":981579400,"Sid":"zWvteTWqBop4heoT","Skey":"@crypt_2ccf8ab9_a710cf413c932e201987599558063c8e","DeviceID":"e358217921593270"},"Msg":{"Type":1,"Content":"test","FromUserName":"@60eef3f2d212721fda0aae891115aa7a","ToUserName":"@@6a5403f510a3192454ed1afebd78ec6033d5057c9038d7b943b201f0a74987d4","LocalID":"15300708105840758","ClientMsgId":"15300708105840758"},"Scene":0} reqeusts.post( url=url, json={ phone:123123123123, password:asdfasdf } ) reqeusts.post( url=url, data=bytes(json.dumps({ phone:123123123123, password:asdfasdf }),encoding=utf-8) ) 31