flask 基础

1,环境安装

  1, mkvirtualenv name -p python3
  2, pip install flask==1.0.3

环境变量配置:一般不用,只用在部署项目时,

export FLASK_APP=xx.py # 指定flask应⽤所在的⽂件路径
export FLASK_ENV=development # 设置项⽬的环境, 默认是⽣产环境
flask run -h 0.0.0.0 -p 8000 # 启动测试服务器并接受请求

2,路由定义 

1,路由一定要以‘/’开头
2,可以通过app.url_map属性来获取所有路由(url资源段)
3,可以通过method 方法指定参数来设置路由的请求方式

自定义路由转换器
1,自定义路由转换器类,继承BaseConverter
2,定义属性regex,设置匹配规则
3,添加自定义转换器

示例代码:

from flask import Flask

app = Flask(__name__)

# 1. URL必须以/开头
# 3. 可以通过methods参数来设置路由支持的请求方式
@app.route('/index', methods=['POST', 'GET'])
def index():

    return "index"


if __name__ == '__main__':
    # 2.可以通过app.url_map属性来获取所有的路由规则 (URL资源段 支持的请求方式 视图函数的标记)
    print(app.url_map)
    # for rule in app.url_map.iter_rules():
    #     print(rule.rule, rule.methods, rule.endpoint)
    app.run(debug=True)

3,路由变量

  正则对路由变量进行格式过滤,失败会返回404,

# 路由变量: 实现动态URL  让一个视图函数可以绑定"一类URL"
# 获取某本书   GET  /books/(?P<pk>\d+)

# 路由变量格式:  /user/<路由变量的名称>


from flask import Flask
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# @app.route('/user/<userid>')
# def index(userid):  # 一旦定义了路由变量, 必须定义同名形参来接收路由变量的值
#     print(userid)
#     return "index"


# 正则转换器: 对路由变量进行格式过滤  过滤失败会返回404
# 格式: /user/<转换器名:路由变量>
@app.route('/user/<int:userid>')  # int转换器: 要求路由变量必须能够转为int
def user(userid):

    print(type(userid))
    return 'user'

自定义转换器的使用: 

  1. 自定义转换器类 继承BaseConverter
  2. 定义属性regex, 设置匹配规则
  3. 添加自定义转换器
# 所有的内置转换器都继承BaseConverter

"""自定义转换器
1. 自定义转换器类 继承BaseConverter
2. 定义属性regex, 设置匹配规则
3. 添加自定义转换器
"""
class MobileConverter(BaseConverter): # 自定义转换器类
    # 定义属性regex, 设置匹配规则
    regex = r'1[3-9]\d{9}$'  # 规则不要添加开头的^

# 添加自定义转换器  {转换器名: 转换器类}
app.url_map.converters['mob'] = MobileConverter


@app.route('/home/<mob:mobile>')  # 使用自定义的转换器
def home(mobile):
    return 'home'


if __name__ == '__main__':
    # 获取所有的转换器 {转换器名: 转换器类}
    # print(app.url_map.converters)
    app.run(debug=True)

 

4,flask接收前端的4中方式

  1,查询字符串方式  request.args

 # 获取查询字符串 -> request.args 类字典对象
    # print(request.args.get('name'))

  2,获取form_data表单传参   request.form

# 获取请求体-键值对(表单) -> request.form    类字典对象
    # print(request.form.get('username'))

  3,获取请求体传参  文本   request.data  |  request.json

 # 获取请求体-文本(json) -> request.data/request.json
    # print(request.data)  # bytes类型
    # print(request.json.get('name'))  # 会将json字符串自动转为字典

  4,获取请求体传参   文件  request.files

# 获取请求体-文件(图片) -> request.files 类字典对象
    file = request.files.get('avatar')  # type: FileStorage
    # 将文件保存到本地
    # file.save('123.png')
    # 获取文件的二进制数据
    file_bytes = file.read()

完整代码:

from flask import Flask, request
from werkzeug.datastructures import FileStorage

app = Flask(__name__)


@app.route('/', methods=['POST', 'GET'])
def index():
    # 获取请求的URL
    # print(request.url)
    # 获取本次请求的请求方式
    # print(request.method)
    # 获取本次请求的请求头
    # print(request.headers)  # 类字典对象 可以像字典一样赋值和取值
    # print(request.headers.get('Host'))  # 建议使用get方法, 不存在会返回None, 不报错

    # 请求传递数据的方式 1> URL路径参数-> 路由变量 2> GET 查询字符串 xx?name=xx&age=20  3> POST 请求体 键值对(表单)/文本(json)/文件(图片) 4> 请求头 -> request.headers

    # 获取查询字符串 -> request.args 类字典对象
    # print(request.args.get('name'))

    # 获取请求体-键值对(表单) -> request.form    类字典对象
    # print(request.form.get('username'))

    # 获取请求体-文本(json) -> request.data/request.json
    # print(request.data)  # bytes类型
    # print(request.json.get('name'))  # 会将json字符串自动转为字典

    # 获取请求体-文件(图片) -> request.files 类字典对象
    file = request.files.get('avatar')  # type: FileStorage
    # 将文件保存到本地
    # file.save('123.png')
    # 获取文件的二进制数据
    file_bytes = file.read()
    print(file_bytes)
    return "index"


if __name__ == '__main__':
    app.run(debug=True)
View Code

 

响应:

1,访问静态文件步骤:

  1,将静态文件放入static文件夹中

  2,使用flask内置的静态文件路由进行访问  http://127.0.0.1:5000/static/s.jpg

from flask import Flask
app = Flask(__name__)

if __name__ == '__main__':
    app.run(debug=True)

注意:只要在与当前同级目录下建立static文件,然后将图片文件放入该文件加下,启动程序,访问/static/xxx.jpg便可以

 2, 后端模板渲染步骤:

  1,将模板放入template文件夹中,指定模板语言

  2,使用render_template函数进行渲染

  3,在模板语言中使用模板语言来替换

@app.route('/',methods=["GET"])
def index():
    keyword = 'hello'
    html_str = render_template('baidu.html',kw=keyword)
    return html_str

template文件中html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    你输入的内容为: {{ kw }}
</body>
</html>
View Code

3,自定义响应对象 (需要设置响应头的时候才使用自定义响应对象)

@app.route('/demo1')
def demo1():
# 视图函数可以返回str、bytes类型数据,并且内部会自动包装为Response类型的响应对象
# 1,创建自定义响应对象,需要设置响应头的时候
response = make_response('demo1')
# 2,设置响应头, 类字典对象
response.headers['name'] = 'xxx'
return response

4,返回json数据  jsonify会将字典封装为json对象,并且将content_type设置为application/json  (访问浏览器进行测试)

# 4, 返回json
@app.route('/demo2')
def demo2():
    dict = {'name':'sd'}
    #jsonify可以将字典,关键字参数封装成json对象返回给前端,并且将content_type设置为application/json
    return jsonify(dict)

5,重定向 :设置响应状态为301/302,响应头Location:目标url

def demo3():
    # return redirect('http://www.baidu.com')
    # return redirect('/demo2')  #直接访问本网站

    # 可以根据视图函数的变偶记获取对应的url的资源段
    # url = url_for('demo2')  #根据函数名找到对应的url
    # print(url)

    # 开发中一般这样使用,考虑url重构
    # return redirect(url_for('demo2'))

    url = url_for('demo4',userid = 11)  #传递的参数,先使用url_for获取访问函数demo4的url,然后进行重定向(可以拼接参数)
    return redirect(url)


@app.route('/demo4/<userid>')
def demo4(userid):
   return 'demo4_%s'%userid

6,自定义状态码:return的三段参数(响应体,响应状态码,响应头)

# 6自定义状态码
@app.route('/demo5')
def demo5():
    #设置自定义状态,第二个返回值,用于自定义交互规则,700密码错误等
    # return  三段参数 (响应体,状态码,响应头)
    # return ‘demo5’,700,{'name':'xxx'}
   return 'demo5',700

 7,状态保持(session和cookie)

  1,cookie

from flask import Flask, make_response, Response, request

app = Flask(__name__)

@app.route('/')
def index():
    # 后端设置cookie: 设置响应头的set_cookie字段

    # 创建响应对象
    response = make_response('index')  # type: Response
    # 设置响应头  value值必须是str/bytes
    response.set_cookie('per_page', '10', max_age=86400)

    # 删除cookie数据   本质: max-age=0
    # response.delete_cookie('per_page')
    return response


@app.route('/demo1')
def demo1():
    # 获取cookie: 浏览器会自动携带cookie数据给服务器, 通过请求头的cookie字段
    per_page = request.cookies.get('per_page')  # 类字典对象
    print(per_page)

    return 'demo1'

  2,session  (flask的session默认是存储在浏览器的cookie中的)

from datetime import timedelta
from flask import Flask, session

app = Flask(__name__)
# 设置应用秘钥 用于对session数据进行签名
app.secret_key = 'test'
# 设置session的过期时间  默认为31天
app.permanent_session_lifetime = timedelta(days=7)


@app.route('/')
def index():
    # 记录session数据  类字典对象
    session['userid'] = 11
    # 设置session支持过期时间
    session.permanent = True
    return "index"


@app.route('/demo')
def demo():
    # 获取session数据
    print(session.get('userid'))

    # 删除session数据 本质:max_age=0 设置过期时间为0
    session.pop('userid', None)
    return 'demo'

if __name__ == '__main__': app.run(debug=True)

注意:flask的session默认是存储在浏览器的session中的,只是经过简单的base64进行加密,使用时一般都要修改存储位置:设置方式如下

from datetime import timedelta
from flask import Flask, session
from flask_session import Session
from redis import StrictRedis

app = Flask(__name__)

# 设置session的配置
app.config['SESSION_TYPE'] = 'redis'  # 设置存储系统
app.config['SESSION_REDIS'] = StrictRedis(host='127.0.0.1', port=6379)  # 指定redis客户端
app.config['SESSION_USE_SIGNER'] = True # 设置对session进行签名
app.config['SECRET_KEY'] = 'test'  # 设置应用秘钥

# 初始化组件
Session(app)


@app.route('/')
def index():
    # 记录session数据  类字典对象
    session['userid'] = 11
    return "index"


@app.route('/demo')
def demo():
    # 获取session数据
    print(session.get('userid'))

    # 删除session数据
    # session.pop('userid', None)
    return 'demo'


if __name__ == '__main__':
    app.run(debug=True

8,flask对象初始化参数

from flask import Flask
import sys

# 记录模块的查询路径  包含 项目目录, 解释器目录, 第三方包的安装目录
print(sys.path)

app = Flask(__name__,  # 导入名称, flask会根据该参数查询静态/模板文件存储路径
            # 官方建议直接使用__name__, 如果使用该值, 则会从当前文件所在的目录中查询静态/模板文件存储路径
            static_folder='static1',  # 设置静态文件的存储路径 ,
            static_url_path='/res/img',  # 设置静态文件的访问路径  /res/img/oldyang.jpg
            template_folder='templates'  # 设置模板文件的存储路径
            )

@app.route('/')
def index():
    return "index"

print(index.__name__)


if __name__ == '__main__':
    app.run(debug=True)

 

 9,异常

 

 请求钩子(相当于django的中间件)

@app.before_first_request(第一个访问web应用会触发,初始化处理)

@app.teardown_request(响应对象包装为Response对象后触发,无论是否异常都会触发,相当于fanilly)

 

 

 

 蓝图:

 

 

 

 

 上下文:

 

 装饰器wraps的使用:因为引用发生了变化

 

 flask的配置:

通过app.config

 

 

动态创建应用 ,(添加蓝图创建应用)

 

 

 缺点:重要配置容易泄露

从环境变量中加载:

  先从对象中加载默认配置,再通过环境变量重载隐私配置

 

posted @ 2019-11-09 19:45  王军的个人博客  阅读(189)  评论(0编辑  收藏  举报