知识点(持续更新)
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