这个笔记记得比较乱,当时想到什么就记什么啦,思想比较天马行空,(<_<),找个时间再整理吧
pip 命令:
pip freeze > requirements.txt 把当前环境中安装的包列表进行导出
Flask程序的开发步骤:
1,导包from flask import Flask
2,创建Flask 应用对象
app=Flask(__name__)
3,通过route装饰器,将url路径与视图函数绑定在一起
@app.route
def hello():
return
4,通过run命令运行起来
if __name__ = "__main__":
app.run()
Flask中的路由配置:
1,同一个url地址可以指向多个视图函数,谁定义在上,谁会执行
2、同一个视图函数可以映射到多个url地址上,可以添加多个注解
3、指定以何种方法访问视图函数,指定methods=["GET", "POST"]
4,可以进行域名的反向解析。url_for("视图函数名")
Flask从路径中提取参数:
Flask中只有一种关键字参数
"/id/<id>" 要提取参数值需要使用<>包裹一个变量名,Flask会把/后的部分作为值传给视图函数的指定参数。
<参数名>默认按照字符串进行截取
<类型名:参数名>匹配指定类型的值作为参数传递给视图函数
内置类型转换器:
int:
float:
path:
自定义类型转换器:
1,定义转换器
class 转换器的类名(BaseConverter):
def __init__(self, url_map, *args):
super(转换器的类名, self).__init__(url_map)
2, 注册转换器
app.url_map.converters["xx"]=转换器的类型名
3,使用自定义转换器
@app.route("/<xx('\d{3}'):arg>")
def fun(arg):
return "hello %s" % arg
文件上传步骤:
上传方:
form表单:
<form method="POST" action="/upload" enctype="multipart/form-data">
<input type="file" name=""><br>
<input type="submit" value="上传">
</form>
接收方:
定义函数:
@app.route('/upload')
def upload():
pic_file = request.files.get("pic")
if pic_file:
pic_file.save('./static/')
else:
return '未接收到文件'
视图异常处理:
1,抛出异常 abort(404)
2,接收异常
@app.errorhandler(404)
def error(e):
return '页面不存在:e'
Cookie:
由服务器创建,随着响应发送到浏览器,由浏览器保存,在浏览器下次发起请求时一起发送到服务器并处理的技术了 。 是HTTP协议中的一部分
响应中: Set-Cookie: 键=值;
Flask中的响应对象
response.set_cookie('键', '值', max_age=3600)
request.cookie.get('键')
response.delete_cookie('键')
生命周期:
在响应中添加Cookie
关闭浏览器
通过max_age设置Cookie的销毁时间
Session:
1,设置SECRET_KEY, 安全字符串
2,往session设置值。session['键'] = 值
3,获取session中的数据的值。session.get("键")
生命周期:
创建:第一次使用Session的时候创建
销毁:Session有默认销毁时间
请求上下文对象:
请求上下文(request context)
request和session都属于请求上下文对象
应用上下文(application context)
current和g 属于应用上下文对象
teardown 拆除
pymysql 链接数据库
from pymysql import *
def main():
# 创建Connection连接
conn = connect(host='localhost',port=3306,database='jing_dong',
user='root',password='mysql',charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
# 执行insert语句,并返回受影响的行数:添加一条数据
# 增加
count = cs1.execute('insert into goods_cates(name) values("硬盘")')
conn.commit()
# 关闭Cursor对象
cs1.close()
# 关闭Connection对象
conn.close()
if __name__ == '__main__':
main()
字符串过滤器
safe:禁止转义
trim:去除两端的空格
lower:转换成小写
upper:转换成大写
列表过滤器
first:取第一个
last:取最后一个
length:长度
sum: 总和
sort:种类
2秒后跳转
2秒后跳转
response=make_response('两秒后跳转至首页')
response.headers['Refresh']=" 2;url=/ "
flask-migrate
导包:
创建对象:
manager=Manager(app) # 添加脚本管理对象
migrate=Migrate(app, db) # 创建数据库迁移对象
manager.add_command('db', MigrateCommand) # 添加迁移命令
需要在命令行注册迁移命令
常用命令
python 文件名 db
init: 初始化命令,保存模型对象的初始状态
migrate: 比较当前的模型类和原来的模型类是否有变更,并把变更记录下来,变更可以使用一个版本号识别
upgrade:更新数据,把数据库升级到指定版本
downgrade:把数据库降级到指定版本,
history:查看版本历史
base:原始版本,在执行migrate命令时创建
使用蓝图对象规划项目
1,创建一个模块目录,用来存放一个功能
2,在模块目录中的__init__.py中创建蓝图对象
3,单独提供views.py用来存放视图函数,视图函数使用蓝图对 象.route()注册路径
前端页面跳转
window.location.href = 'url'
前端页面定时跳转
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
var time=4;
var timer = setInterval(function(){
var str = document.getElementById("second");
if(time>=1){
str.innerHTML=time;
time--;
}else{
clearInterval(timer);
location.href = "http://www.baidu.com";
}
},1000)
</script>
</head>
<body>
注册成功,<span id="second">5</span>秒后自动为您转跳回首页
</body>
</html>
web_html.py 创建一个映射,提供静态html文件
from flask import Blueprint,current
# 创建蓝图
html = Blueprint('html', __name__)
@html.route('/<re(r".*"):file_name>')
def get_html(file_name):
'''提供html文件'''
if not file_name:
# file_name 为空
file_name = 'index.html'
if file_name != 'favicon.ico': # 请求不为图标
file_name = 'html/'+file_name
# 使用wtf帮助我们生成csrf_token字符串
csrf_token = generate_csrf()
# 为用户设置cookie csef_token
response = make_response(courrent.app.send_static_file(file_name))
response.set_cookie('csrf_token', csrf_token)
return response
/util/commons.py
自定义一个正则转换器
from werkzeug.routing import BaseConverter
class RegexConverter(BaseConverter)
def __init__(self, url_map, regex)
super(RegexConverter,self).__init__(url_map)
self.regex = regex
/api01/verify_code.py
RESTFul风格
from . import api
from ihome.utils.captcha.captcha import captcha
@api.route('/image_code/<image_code_id>')
def get_image_code(image_code_id):
'''提供图片验证码'''
# 业务处理
# 生成验证码图片
# 名字,验证码真实值,图片的二进制内容
name,text,image_data = captcha.generate_captcha()
# 保存验证码的真实值,编号
try:
redis_store.setex('image_code_%s'%iamge_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, TEXT)
except Exception as e:
current_app.logger.error(e)
resp = {
'errno':RET.DBERR,
'errmsg':"保存验证码失败"
}
return jsonify(resp)
# 返回验证码图片
response = make_response(image_data)
response.headers['Content-Type'] = 'image/jpg'
return response
用户注册
# POST /api01/users
@api.route('/users', methods=['GET', 'POST'])
def register():
'''用户注册'''
# 接收参数, 手机号, 短信验证码,密码,json格式数据
# request.get_json方法能将请求体的json数据转换为字典
req_dict = request.get_json()
mobile = req_dict['mobile']
sms_code = req_dict['sms_code']
password = req_dict['password']
# 校验参数
if not all([mobile, sms_code, password]):
resp = {
'errno':RET.PARAMERR,
'errmsg':'参数不完整'
}
return jsonify(resp)
# 业务处理
# 判断手机号格式
if not re.match(r'1[34578]\d{9}', nobile):
resp = {
'errno': RET.DATAERR,
'errmsg':'手机号格式不正确'
}
return jsonify(resp)
# 判断短信验证码是否过期
try:
# 获取真实的短信验证码
real_sms_code = redis_store.get('sms_code_%s'%mobile)
except Exception as e:
current.app.logger.error(e)
resp = {
'errno':RET.DBERR,
'errmsg':'查询验证码失败'
}
return jsonify(resp)
if real_sms_code is None:
resp = {
'errno':RET.NODATA,
'errmsg':'验证码已过期'
}
return jsonify(resp)
# 判断用户输入的验证码是否正确
if sms_code != real_sms_code:
resp = {
'errno':RET.DATAERR,
'errmsg':'验证码不正确'
}
return jsonify(resp)
# 判断手机号是否已注册
try:
user = User.query.filter_by(phone=mobile).first()
except Exception as e:
current.logger.error(e)
resp = {
'errno': RET.DBERR,
'errmsg':'查询失败'
}
return jsonify(resp)
if user is not None:
resp = {
'errno':RET.DATAEXIST,
'seemsg':'手机号已注册'
}
return jsonify(resp)
前端根据name获取cookie(固定格式)
function getCookie(name){
// 根据name提取相应的cookie值
// \b代表单词边界
var r = document.cookie.match("\\b"+csrf_token+"=([^;]*)\\b");
return r ? r[1] : undefined;
}
登陆检测装饰器login_required
/utils/commons.py # 路径
def login_required(view_func):
def wrapper(*args, **kwargs):
user_id = session.get('user_id')
if user_id is not None:
return view_func(*args, **kwargs)
else:
# 用户未登录
resp = {
'errno':RET.SESSIONERR,
'errmsg': '用户未登录'
}
return jsonify(resp)
return wrapper
Night gathers, and now my watch begins. It shall not end until my death. I shall take no wife, hold no lands, father no children. I shall wear no crowns and win no glory I shall live and die at my post. I am the sword in the darkness. I am the watcher on the walls
用户注册页面:
注册一个视图函数将访问<filename>请求进行处理,将static/html目录下的文件发送给用户
功能点1:编写自定义类型转换器
功能点2:需要为请求添加一个Cookie,防止csrf攻击
图片验证码:
功能点:用户在首次注册页面和点击图片验证码时,会重新请求图片验证码 /api01/image_codes/<image_code_id>
1,生成验证码(调用工具)
2,保存验证码图片到redis(键是image_code_id)
3,将图片发送给浏览器(设置Content-Type:'image/jpg')
RESTFul风格
出发点:互联网所有的内容都是资源
我们对资源的访问:增删改查
可哈希,不可哈希类型
可哈希:不可变类型 string, tuple, 对象集objects
不可哈希:可变型 列表list , 字典dict , 集合set