flask 诞生于2010年,是Armin ronacher用python语言基于Werkzeug工具箱编写的轻量级web开发框架
Flask本身相当于一个内核,其他几乎所有功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用到第三方的扩展来实现。比如可以用Flask扩展加入ORM,窗体验证工具,文件上传,身份验证等。Flask没有默认使用的数据库,可以选择Mysql,也可以使用NoSQL.
其WSGI工具箱采用Werkzeug(路由模块),模板引擎则使用Jinja2,这两个也是Flask框架的核心
#导入Flask类
from flask import Flask
#Flask类接收一个参数__name__
app=Flask(__name__)
#装饰器的作用是将路由映射到视图函数index
@app.route('/')
def index():
return' hello_world'
#Flask应用程序实例的run方法启动WEB服务器
if __name__=='__main__':
app.run()
Flask对象的初始化参数
应用程序的配置参数
app.run() 运行参数
环境变量一般是指操作系统中用来指定操作系统运行环境的一些参数,如临时文件夹位置和系统文件夹位置等,环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或多个应用程序所将使用到的信息
通俗理解就是,环境变量就是我们设置在操作系统中,由操作系统代为保存的变量值
在linux系统中设置和读取环境变量的方式如下:
在终端设置的环境变量在pycharm中启动不起作用,原因是终端与pycharm是两个不同的环境
优点:
缺点:
项目中常用的方式
#应用程序的配置参数
"""
#1.配置对象方式加载配置信息
# class DefaultConfig(object):
# '''默认配置'''
# SECRET_KEY='fdkasfjowq'
#2.从配置文件中加载 setting.py
#3.从环境变量中加载配置文件
"""
app=Flask(__name__,static_url_path='/s',static_folder='static_files')
#设置
# app.config.from_object(DefaultConfig)
# app.config.from_pyfile('setting.py')
app.config.from_envvar('PROJECT_SETTING',silent=True)
#silent 表示系统环境变量中没有设置相应值时是否抛出异常
# False 表示不安静处理,没有值时报错通知,默认为False
# True 表示安静处理,即没有值也让Flask正常的运行
#终端:export PROJECT_SETTING=setting.py
#定义视图
@app.route('/')
def index():
#读取配置信息
print(app.config['SECRET_KEY'])
return '百度'
#动态路由
"""
@app.route('/user/')
def user(name):
return 'hello %s'%name
"""
if __name__ == '__main__':
app.run()
# 遍历路由信息
# for rule in app.url_map.iter_rules():
# print('name={},path={}'.format(rule.endpoint, rule.rule))
# print(list(app.url_map.iter_rules()))#
# [ index>, ' (HEAD, GET, OPTIONS) -> static>]
# print(app.url_map)
#通过访问 / 地址,以json的方式返回应用内的所有路由信息
@app.route('/')
def route_app():
'''主视图,返回所有视图网址'''
rules_iterator=app.url_map.iter_rules()
return json.dumps({rule.endpoint:rule.rule for rule in rules_iterator})# {"route_app": "/", "static": "/s/"}
#蓝图的应用
#单个文件
"""
#1.创建蓝图对象
user_bp=Blueprint('user',__name__)
#2在蓝图上操作,注册路由,指定静态文件夹,注册模板过滤器
@user_bp.route('/')
def user_profile():
return 'user_profile'
#3.在应用对象上注册这个蓝图
app.register_blueprint(user_bp)
"""
#目录中使用
""""""
#1.创建python包--在__init__文件中创建蓝图对象
#2.创建视图文件 在视图文件中操作
#3.在应用上注册这个蓝图 使用prefix给路由加前缀 先指定前缀再指定路由 访问时前缀可为空
from goods import good_bp
app.register_blueprint(good_bp)
#将蓝图目录下的static_admin目录设为静态目录
admin=Blueprint('admin',__name__,static_folder='static_admin')
app.register_blueprint(admin,url_prefix='admin')
#使用/admin/static_admin/访问static_admin目录下的静态文件,也可通过static_url_path改变路径
admin=Blueprint('admin',__name__,static_folder='static_admin',static_url_path='/lib')
app.register_blueprint(admin,url_prefix='/admin')
#蓝图内部的模板目录
admin=Blueprint('admin',template_folder='my_templates')
@app.route('/user/' )#等价于@app.route('/user/')
def user(name):
return 'hello %s'%name
from werkzeug.routing import BaseConverter
#**加粗样式**1.自定义转换器类(需要导入werkzeug.routing /BaseConverter)
class MobileConverter(BaseConverter):
'''手机号格式'''
regex=r'1[3-9]\d{9}'#regex是固定的 正则表达式
#2.将自定义的转换器告知Flask应用
#将自定义的转换器添加到转换器字典中,并指定转换器使用时的名字为:mobile
app.url_map.converters['mobile']=MobileConverter
#3.在使用转换器的地方定义使用
@app.route('/user/' )
def sen_code(mob_num):
return 'send_code{}'.format(mob_num)
#其他参数request 需要导入request
#若想获得请求/articles?channel_id=1中channel_id的参数,可以按如下方式使用:
@app.route('/articles')
def get_articles():
channel_id=request.args.get('channel_id')
return 'get articles or channel {}'.format(channel_id)
#上传图片 客户端上传图片到服务器并保存到服务器中
@app.route('/upload',methods=['POST'])
def upload_file():
f=request.files('images')
#with open('./demo.png','wb')as new_file:
#new_file.write(f.read())
f.save('./demo.png')
return 'ok'
#响应模板的渲染 render_template
@app.route('/index2')
def home():
# mint=123
# mstr='itcast'
data=dict(
my_str='fsfs',
my_int=432
)
# return render_template('index2.html',my_str=mstr,my_int=mint)
# return render_template('index2.html',my_str='intste',my_int=232)
return render_template('index2.html',**data)
#重定向 需要导入redirect
"""
@app.route('/demo2')
def demo2():
return redirect('http://www.baidu.com')
"""
#返回JSON 需要导入jsonify
@app.route('/demo3')
def demo3():
json_dict={
'user_id':10,
'user_name':'laowang'
}
return jsonify(json_dict)
#自定义状态码与响应头
#元组方式
"""
@app.route('/demo4')
def demo4():
# return '状态码为666',666 #响应体 状态码 响应头 省略时只能从右边省略
# return '状态码 666',666,[('Itcast','Python')]
return '状态码为666',666,{'Itcast':'Python'}
"""
#2.make_response方式
@app.route('/demo5')
def demo5():
resp=make_response('make_response测试')
resp.headers['Itcast']='Python'
resp.status='404 Not Found'
return resp
#Cookie设置 只在响应对象中设置
"""
@app.route('/cookie')
def s_cookie():
resp=make_response('set cookie ok')
resp.set_cookie('username','itcast',max_age=3600)# cookie名字 cookie的值 max_age(可选参数)设置有效期
return resp
"""
#Cookie读取 需要导入request
"""
@app.route('/getcookie')
def get_cookie():
resp=request.cookies.get('username')
return resp
"""
#Cookie删除
"""
@app.route('/deletecookie')
def delete_cookie():
resp=make_response('delete cookie')
resp.delete_cookie('username')
return resp
"""
#Session 需要先设置SECRET_KEY
class DefaultConfig(object):
SECRET_KEY='gfsgsg'
app.config.from_object(DefaultConfig)#app.secret_key='ghkggjk'
# Session设置 需要先导包session
@app.route('/setsession')
def set_session():
session['username']='itcast'#以字典形式设置保存
return 'set session OK'
#读取
@app.route('/getsession')
def get_session():
username=session.get('username')
return 'get session username{}'.format(username)
启动中间件/中间层的作用
请求处理过程: pre_process—>view----->after process
request 请求处理流程:
middleware1.pre_process()–>m2.pre_process()–>m3.pre_process()-->view()–>m3.after_process()–>m2.after_process()–>m1.after_process()
中间件不区分具体哪个视图,对所有视图都生效
#请求钩子 启动中间件/中间层
#1.在第一次请求前调用,可以在此方法内部做一些初始化操作、
@app.before_first_request
def before_first_request():
print('pre_first_request')
#2.在每一次请求前调用,这时已经有请求了,可在这个方法例做校验
#若请求校验不成功,可以直接在此方法中进行响应,直接return之后不执行视图函数
@app.before_request
def before_request():
print('before_request')
# if 请求不符合条件
# return 要返回的响应
#在执行完视图函数之后不保错会调用,并且会把视图函数所生成的响应传入,可以在此方法中对响应做最后一步统一的处理
@app.after_request
def after_request(response):
print('after_request')
response.headers['Content-Type']='application/json'
return response
#每次请求之后都会调用,会接收一个参数,参数是服务器出现的错误信息
@app.teardown_request
def teardown_request(response):
print('teardown_request {}'.format(response))
@app.route('/')
def index1():
print('view called')
return 'index'
上下文,即语境、语意,在程序中可以理解为在代码执行到某一时刻时,根据之前代码所做的操作及下文即将要执行的逻辑,可以决定在当前时刻下可以使用到的变量,或者可以完成的事情
flask中有两种上下文,请求上下文和应用上下文
Flask中上下文对象:相当于一个容器,保存了Flask程序运行过程中的一些信息
#g对象 的使用 相当于一个容器,可以保存数据 适用于当次
from flask import g
def db_query():
user_id=g.user_id
user_name=g.user_name
print('user_id={},user_name={}'.format(user_id,user_name))
@app.route('/')
def get_user():
g.user_id=4213
g.user_name='fds'
ret=db_query()
return 'g对象应用'
#上下文综合应用 1.构建认证机制 2.对于特定视图可以提供强制要求用户登录 3.在所有视图都可以获取用户认证后的身份信息
#特定强制 --装饰器 所有需求--请求钩子
#请求--请求钩子(g对象保存用户身份信息 尝试判断用户的身份 对于未登录的不做处理 放行)--普通视图--强制登录视图--装饰器
#1.请求钩子
from flask import request,abort,current_app,g
@app.before_request
def auther():
'''利用before_request请求钩子,在进入所有视图前先尝试判断用户的身份: return '''
#TODO此处使用鉴权机制(如cookie,session,jwt等)鉴别用户身份信息
#if 已登录用户,用户有身份信息
g.user_id=234
#else 未登录用户,用户无身份信息
# g.user_id=None
#强制登录 装饰器
def login_require(fun):
def wrapper(*args,**kwargs):
#判断用户是否登录
if g.user_id==None:
abort(401)
else:
return fun(*args,**kwargs)
return wrapper
#视图 普通视图 不要求用户登录
@app.route('/')
def index():
return 'get user_id is {}'.format(g.user_id)
#视图 强制用户登录
@app.route('/get')
@login_require
def get_user():
return 'get user_id is {}'.format(g.user_id)
#app_context
from flask import Flask
app=Flask(__name__)
app.redis_cli='redis_cli'
from flask import current_app
with app.app_context():
print(current_app.redis_cli)
#request_context
from flask import Flask
app=Flask(__name__)
environ={'wsgi.version':(1,0),'wsgi_input':''}
with app.request_context(environ):
print(request.path)
class DemoResource(Resource):
def get(self):
return ('user_id':1,'name':'itcase')
# 对于诸如此类的接口,能否在某处统一格式化成上述需求格式
{'messgae':'ok','data':{'user_id':1,'name':'itcast'}}
# 解决:
# Flask-RESTful的Api对象提供了一个representation的装饰器,允许定制返回数据的呈现格式
api=Api(app)
@api.representation('application/json')
def handle_json(data,code,headers):
#TODO 此处添加自定义处理
return resp
# Flask-RESTful原始对于json的格式 处理方式如下:
# 代码如下:flask_restful.representations.json