flask 简介
Flask 简介
什么是flask?
用于进行 web开发的python框架
业务逻辑处理
协议处理不需要操心
1
2
Flask:使用架构MVT
M:model 用于和关系型数据库交互
V: View 接受请求 处理请求 返回相应
T:Template: 模板 用于展示一个html页面
为什么采用mvt
目的:低耦合 模块化
优点:
处理内容
显示内容相互独立
互不影响
2.虚拟环境
为什么需要虚拟环境?
问题一:多个项目 包的版本不同
问题二:在服务器上运行 太过复杂
希望项目之间包不冲突
虚拟环境:在安装python包时 相互独立不影响
具体安装:
sudo pip install virtualenv
sudo pip install virtualenvwrapper
安装之后配置环境
1.创建目录用来存放虚拟环境
mkvirtualenv -p python3 虚拟环境名称
2.使用虚拟环境
workon 查看
workon py3_flask
3.退出
deactivate
4.删除虚拟环境
rmvirtualenv 名称
使用flask创建web开发
1.引入 from flask import Flask
2.创建 app = Flask(__name__)
3.定义视图 配置路由
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return 'hello world'
if __name__ == '__main__':
app.run()
配置环境变量
三种方式进行配置 config
1 way: object
app.config.from_object(Config)
2 way: file
app.config.from_pyfile('d2_config1.py')
3 way: env
app.config.from_envvar('CONFIG')
from flask import Flask
app = Flask(__name__)
from config import Config
# class Config(object):
# DEBUG = True
# 加载配置
# 方式1:对象
app.config.from_object(Config)
# 方式2:文件
# app.config.from_pyfile('d2_config1.py')
# 方式3:环境变量
# app.config.from_envvar('CONFIG')
if __name__ == '__main__':
app.run()
三种方式中:主要用对象 因为类可以继承
配置读取
app.config[key]
视图常用
flask 返回值
1.字符串
2.html
3.json
4.重定向
json 是一种表示数据的格式
xml 现在都用json
目的是跨语言 python java 都可以使用
就是一种格式
ajax的时候使用json数据
js和python之间的数据交互
视图怎么返回json格式的数据
jsonify(key=value)
重定向
redirect
接受用户名 密码 和 验证 重定向
url_for 根据函数名跳转url
from flask import Flask, jsonify, redirect, url_for
app = Flask(__name__)
@app.route("/")
def index():
return 'hello world'
@app.route("/detail")
def detail():
# return jsonify(word1='hello', word2='world')
return redirect(url_for('index'))
return redirect('/')
if __name__ == '__main__':
app.run()
异常处理
abort(状态码) 直接abort状态码
@app.errorhandler(状态码) 对某一状态码进行同一处理
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
# abort(404)
return 'hello world'
@app.errorhandler(404)
def error404(e): # 参数e表示exception 对象
return 'your net is error'
if __name__ == '__main__':
app.run()
请求钩子
针对大部分视图函数都需要执行的代码
1.定义一个函数 都调用
2.请求钩子
每次请求相应都会被调用
根据请求地址进行route匹配
before_first_request
before_request 常用
找到视图函数
after_request 常用
teardown_request
有什么用?
当大部分视图中都要执行一段代码时 可以将这段代码写到钩子函数中
from flask import Flask
app = Flask(__name__)
# 请求勾子
@app.route('/')
def index():
print('--------index')
return 'hello world'
@app.before_first_request
def before_first_request():
print('--------before_first_request')
@app.before_request
def before_request():
print('--------before_request')
@app.after_request
def after_request(response):
#response表示视图函数返回的结果对象
print('--------after_request')
return response
@app.teardown_request
def teardown_request(e):
#e表示Exception对象
#当视图函数发生错误后,after_request函数不再执行,直接执行此函数
print('--------teardown_request')
if __name__ == '__main__':
app.run(debug=True)
路由配置
在路由中配置 <> 可以提取数据 还可以限定据类型
postman 谷歌浏览器插件
浏览器请求模拟
路由指定 请求参数
@app.route('/<int:news_id>', methods=['GET', 'POST'])
get put post delete
路由装饰器内部机制
print(app.url_map)
列表
rule对象 表达式 请求方式 函数
1.创建rule对象
Ruel(<news_id>, GET, detail)
2.创建Map对象
2.1 内置转换器
3.为app.url_map属性赋值
from flask import Flask
from werkzeug.routing import Map
app = Flask(__name__)
@app.route('/<int:news_id>', methods=['GET', 'POST'])
def index():
return 'hello world'
""" what app did
Map([<Rule '/' (HEAD, OPTIONS, GET) -> index>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
<class 'werkzeug.routing.Map'>
"""
"""
1.创建Rule对象
2.创建Map对象 并且内置转化器
3.为app.url_map属性赋值
"""
if __name__ == '__main__':
print(type(app.url_map))
print(app.add_url_rule)
print(app.url_map)
app.run()
从之前的helloworld.py文件中,我们已经看到,一个URL要与执行函数进行映射,使用的是@app.route装饰器。@app.route装饰器中,可以指定URL的规则来进行更加详细的映射。
数据约束类型:
代码 类型
string 默认的数据类型,接受没有任何斜杠/的字符串
int 整形
float 浮点型
path 和string类似,但是可以传递斜杠/
uuid uuid类型的字符串
any 可以指定多种路径
尖括号是固定写法
如果不想定制子路径来传递参数,也可以通过传统的?=的形式来传递参数。
上下文
什么是上下文?
上下文相当于一个容器 保存了flask程序运行时的一些信息
flask中上下文 分为两种 请求上下文 应用上下文
application context request context
application 当调用app=Flask(__name__)创建的这个对象app
request 指的是每次 http 请求发生时 WSGI server 调用Flask.__call__() 之后 在flask内部创建request对象
application 表示相应于WSGI请求本身 request表示每次http请求
application的生命周期大于request 一个application 存活期间 可能发生多次http请求 所以会有多个request
from flask import Flask
from flask import request
"""上下文
上下文相当于一个容器 保存了flask程序运行时的一些信息
flask中上下文 分为两种 请求上下文 应用上下文
application context request context
application 当调用app=Flask(__name__)创建的这个对象app
request 指的是每次 http 请求发生时 WSGI server 调用Flask.__call__() 之后 在flask内部创建request对象
application 表示相应于WSGI请求本身 request表示每次http请求
application的生命周期大于request 一个application 存活期间 可能发生多次http请求 所以会有多个request
"""
app = Flask(__name__)
@app.route('/')
def index():
return 'hello world'
@app.route('/get', methods=['GET'])
def get():
"""
使用postman测试
http://127.0.0.1:5000/get?a=10&b=20&c=30
:return:
"""
print(request.url)
print(request.method)
dict1 = request.args
a = dict1.get("a")
b = dict1.get("b")
c = dict1.get("c")
return '%s-%s-%s' % (a, b, c)
@app.route('/post', methods=['POST'])
def post():
"""
使用postman测试
post form data 在body中设置
:return:
"""
print(request.url)
print(request.method)
dict2 = request.form
username = dict2.get('username')
password = dict2.get('password')
return '%s-%s' % (username, password)
if __name__ == '__main__':
app.run(debug=True)
状态保持
因为 http 是一种无状态协议,浏览器请求服务器是无状态的。
无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。
无状态原因:浏览器与服务器是使用 socket 套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 socket 连接,而且服务器也会在处理页面完毕之后销毁页面对象。
有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等
实现状态保持主要有两种方式:
在客户端存储信息使用Cookie
在服务器端存储信息使用Session
cookie
from flask import Flask, make_response, request
"""状态保持
cookie session
cookie保存在浏览器中 --- 客户端存储
session保存在服务端中 redis --- 服务端存储
"""
"""
Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用
Cookie基于域名安全,不同域名的Cookie是不能互相访问的
如访问itcast.cn时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到itcast.cn写的Cookie信息
浏览器的同源策略
当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器,所以在request中可以读取Cookie信息
step1 创建response 对象
repr = make_response('xxx')
step2 setting cookie
repr.set_cookie(key, value)
get cookie key value
浏览器会将当前网站的所有cookie信息 包含在请求报文中
request.cookies.get(key)
"""
app = Flask(__name__)
@app.route('/set')
def set():
# 创建response对象
response = make_response("hello")
# jsonify() redirect()
# 默认过期时间是关闭浏览器
response.set_cookie("hello", "flask")
# 浏览器将cookie保存起来
# max_age 设置过期时间 单位是秒
# response.set_cookie('hello', 'flask', max_age=60*60*24*7)
# 删除 max_age=-1 在前一秒删除
# response.set_cookie('hello', '', max_age=-1)
return response
@app.route("/get")
def get():
# 浏览器会将当前网站的所有cookie信息 包含在请求报文中
cookie = request.cookies.get("hello")
return cookie
if __name__ == '__main__':
app.run()
session
from flask import Flask
from flask import session
""" 状态保持 session
对于敏感 重要的信息 建议要存储在服务器端 不要存储在浏览器中
在服务器端进行状态保持的方案就是session
session依赖于Cookie
"""
app = Flask(__name__)
# 使用session时 需要制定secret_key
# 进行加密处理
app.secret_key = 'python'
@app.route('/set')
def set():
# session 设置
session['hello'] = 'flask'
return 'ok'
@app.route("/get")
def get():
# session 获取
hello = session.get("hello")
return hello
if __name__ == '__main__':
app.run()
Flask-Script 扩展
作用:
1.通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参
2.Flask-Script 还可以为当前应用程序添加脚本命令
from flask import Flask
""" flask 命令行扩展
1.导包
from flask_script import Manager
2.创建对象
manager = Manager(app)
3.自定义方法
class xxx(Command):
'heiheihei'
4.运行
manager.run()
"""
# 1 引入包
from flask_script import Manager
app = Flask(__name__)
# 2 创建对象 -- 将app作为对象 传入Manager类中
manager = Manager(app)
# 4 自定义方法
from flask_script import Command
class Show(Command):
def __call__(self, *args, **kwargs):
print("这是自定义的方法")
manager.add_command('show', Show())
if __name__ == '__main__':
# app.run()
# 3 运行
manager.run()
蓝图
模块化开发视图
# step1 引入蓝图
from flask import Blueprint
# url_prefix + @route 访问地址
# 'user' + func login() 指向func
# step2 创建蓝图对象
user_blueprint = Blueprint('user', __name__, url_prefix='/user')
# step3 在路由上注册
@user_blueprint.route("/login")
def login():
return 'login'
from flask import Flask
app = Flask(__name__)
from demo6_user import user_blueprint
"""
# 从demo6_user 导入 蓝图
# 注册到当前的flask程序中
app.register_blueprint(user_blueprint)
"""
@app.route("/login")
def login():
return 'login'
if __name__ == '__main__':
print(app.url_map)
app.run()
小扩展
uuid
是个啥东西?
就是一个通用唯一识别码
每次值都是不一样的
uuid.uuid1()
str(uuid.uuid1())