近期学习开发中遇到的一些知识,做的学习笔记,做个小记录,持续更新中…
Dataset基于SQLAlchemy的便利工具
数据集使得数据库中的数据读取和写入数据就像阅读和编写JSON文件一样简单。
dataset对于操作JSON、CSV文件、NoSQL非常好用。
import dataset
连接MySQL数据库:
|
|
一定要注意指定字符编码
|
|
在数据库中查找是否有同时满足多个条件的数据:table.find_one(属性1=属性值1, 属性2=属性值2, ...)
注:find_one
速度很慢
插入数据
dataset会根据输入自动创建表和字段名
|
|
更新数据
|
|
事务操作
事务操作可以简单的使用上下文管理器来实现,出现异常,将会回滚
|
|
从表获取数据
|
|
获取非重复数据
db['user'].distinct('country')
删除记录
|
|
执行SQL语句
|
|
导出数据
|
|
JSON
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,非常易于人阅读和编写。
|
|
MySQL数据库:
分类表-categories,包括类别web,reversing,crypto(加解密),mic等
题目表-tasks,包括题目id,题目名,flag,分值,文件&地址,题目等级,题目详细描述
flag表-flag,包括题目id,用户id,得分,时间戳
用户表-users,包括用户id,用户名,密码
题目分类表-cat_task
,包括题目id,题目类别id
flag表中每条数据由于是有题目ID task_id
和用户ID user_id
来共同确认的,所以采用复合主键:primary key (task_id,user_id)
python装饰器
Decorator通过返回包装对象实现间接调用,以此插入额外逻辑
https://www.zhihu.com/question/26930016
wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器函数中,这使得装饰器函数也有和原函数一样的元信息了
|
|
web框架采用flask
from flask import Flask
引入Flask类,Flask类实现了一个WSGI(Web Server Gateway Interface)
应用
app = Flask(__name__)
app是Flask的实例,它接收包或者模块的名字作为参数,但一般都是传递__name__
|
|
使用app.route
装饰器会将URL和执行的视图函数的关系保存到app.url_map
属性上。处理URL和视图函数的关系的程序就是路由,这里的视图函数就是hello_world
|
|
使用这个判断可以保证当其他文件引用这个文件的时候(例如from hello import app
)不会执行这个判断内的代码,也就是不会执行app.run
函数。
执行app.run
就可以启动服务了。默认Flask只监听虚拟机的本地127.0.0.1
这个地址,端口为5000
。而我们对虚拟机做的端口转发端口是9000
,所以需要制定host和port参数,0.0.0.0
表示监听所有地址,这样就可以在本机访问了。
服务器启动后,会调用werkzeug.serving.run_simple
进入轮询,默认使用单进程单线程的werkzeug.serving.BaseWSGIServer
处理请求,实际上还是使用标准库BaseHTTPServer.HTTPServer
,通过select.select
做0.5秒的while TRUE
的事件轮询。当我们访问http://127.0.0.1:9000/
,通过app.url_map
找到注册的/
这个URL模式,就找到了对应的hello_world
函数执行,返回hello world!
,状态码为200。如果访问一个不存在的路径,如访问http://127.0.0.1:9000/a
,Flask找不到对应的模式,就会向浏览器返回Not Found
,状态码为404
flask中jsonify的作用
jsonify的作用实际上就是将我们传入的json形式数据序列化成为json字符串,作为响应的body,并且设置响应的Content-Type
为application/json
,构造出响应返回至客户端
效果等于json.dumps
jsonify
的Content-Type
字段值为application/json
json.dumps
的Content-Type
字段值为text/html
修改flask中静态文件夹
修改的flask默认的static文件夹只需要在创建Flask实例的时候,把static_folder
和static_url_path
参数设置为空字符串即可。
app = Flask(__name__, static_folder='', static_url_path='')
访问的时候用url_for
函数,res文件夹和static文件夹同一级:
url_for('static', filename='res/favicon.ico')
werkzeug
werkzeug是一个WSGI工具包,可以作为一个Web框架的底层库。它封装好了很多Web框架的东西,例如 Request,Response等等。Flask框架就是一Werkzeug 为基础开发的
generate_password_hash(password)
将用户输入的明文密码加密成密文进行存储
密码加盐哈希函数。用来将明文密码加密,返回加密后的密文,用来进行用户注册
函数定义:
|
|
check_password_hash(hash,password)
验证经过generate_password_hash
哈希的密码,将明文和密文进行比较,查看是否一致,用来验证用户登录
函数定义:
|
|
flask中的session
|
|
由于使用了session,所以需要设置一个secret_key
用来做一些模块的hash
Flask Web Development 中的内容:
SECRET_KEY
配置变量是通用密钥,可在Flask和多个第三方扩展中使用。如其名所示,加密的强度取决于变量值的机密度。不同的程序要使用不同的密钥,而且要保证其他人不知道你所用的字符串。
SECRET_KEY
的作用主要是提供一个值做各种HASH, 是在其加密过程中作为算法的一个参数(salt或其他)。所以这个值的复杂度也就影响到了数据传输和存储时的复杂度。
flask 变量规则
要给URL添加变量部分,你可以把这些特殊的字段标记为<variable_name>
, 这个部分将会作为命名参数传递到你的函数。规则可以用<converter:variable_name>
指定一个可选的转换器
|
|
数据库查询
对dataset的数据查询,使用冒号来为变量传参。
select f.task_id from flags f where f.user_id = :user_id''',user_id=session['user_id'])
模板渲染
使用render_template
方法来渲染模板。将模板名和你想作为关键字的参数传入模板的变量
MySQL
IFNULL(expr1,expr2)
如果expr1不是NULL,IFNULL()
返回expr1,否则它返回expr2。
IFNULL()
返回一个数字或字符串值,取决于它被使用的上下文环境。
max函数是用来找出记录集中最大值的记录
|
|
在使用left jion时,on和where条件的区别如下:
|
|
order by的用法
|
|
group by的用法
|
|
MySQL的左连接、右连接、等值连接
1.左连接(left join )
|
|
ON是连接条件,用于把2表中等值的记录连接在一起,但是不影响记录集的数量。若是表left_table
中的某记录,无法在表right_table
找到对应的记录,则此记录依然显示在记录集中,只是表right_table
需要在查询显示的列的值用NULL替代;
ON连接条件中表n.columnname=xxx
用于控制right_table
表是否有符合要求的列值还是用NULL替换的方式显示在查询列中,不影响记录集的数量;
WHERE字句控制记录是否符合查询要求,不符合则过滤掉
2.右连接(right join)
|
|
3.等值连接
|
|
ON是连接条件,不再与左连接或右连接的功效一样,除了作为2表记录匹配的条件外,还会起到过滤记录的作用,若left_table
中记录无法在right_table
中找到对应的记录,则会被过滤掉;
WHERE字句,不管是涉及表left_table
、表right_table
上的限制条件,还是涉及2表连接的条件,都会对记录集起到过滤作用,把不符合要求的记录刷选掉;
jinja2获取循环索引
|
|
flask 重定向和错误
可以用redirect()
函数把用户重定向到其它地方。放弃请求并返回错误代码,用abort()
函数。
|
|
默认情况下,错误代码会显示一个黑白的错误页面。如果你要定制错误页面,可以使用errorhandler()
装饰器:
|
|
注意 render_template()
调用之后的 404 。这告诉Flask,该页的错误代码是404 ,即没有找到。默认为200,也就是一切正常。
flask CSRF防护机制
|
|
在flask的全局变量里面注冊 上面那个生成随机token的函数
app.jinja_env.globals['csrf_token'] = generate_csrf_token
在网页的模板是这么引入的
|
|
flask上下文处理器
Flask 上下文处理器自动向模板的上下文中插入新变量。上下文处理器在模板渲染之前运行,并且可以在模板上下文中插入新值。上下文处理器是一个返回字典的函数,这个字典的键值最终将传入应用中所有模板的上下文:
|
|
上面的上下文处理器使得模板可以使用一个名为user值为g.user
的变量。不过这个例子不是很有意思,因为g在模板中本来就是可用的,但它解释了上下文处理器是如何工作的。
变量不仅限于值,上下文处理器也可以使某个函数在模板中可用(由于Python允许传递函数):
|
|
日志记录
handler = logging.FileHandler('flask.log', encoding='UTF-8')
1、请求之前设置requestId并记录日志
每个URL请求之前,定义requestId并绑定到g
|
|
2、请求之后添加响应头与记录日志
每次返回数据中,带上响应头,包含API版本和本次请求的requestId,以及允许所有域跨域访问API, 记录访问日志
|
|
basicConfig
方法可以满足你在绝大多数场景下的使用需求,但是basicConfig
有一个很大的缺点。调用basicConfig
其实是给root logger
添加了一个handler(FileHandler )
,这样当你的程序和别的使用了 logging
的第三方模块一起工作时,会影响第三方模块的logger
行为。这是由logger的继承特性决定的
|
|
MySQL字符编码
除了设置数据库的之外,由于dataset默认创建数据库和表的字符集不是utf8,所以需要自己设置,否则会中文乱码,所以需要修改表的字符集
|
|
表的字符集
show create table tasks;
alter table tasks convert to character set utf8;