Flask
官方文档:[http://docs.jinkan.org/docs/flask/index.html]()官方源:https://pypi.org/project/Flask/
简介
Flask 是一个 Python 实现的 Web 开发微框架。
Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现。比如可以用 Flask 扩展加入ORM、窗体验证工具,文件上传、身份验证等。Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL。
其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是 Flask 框架的核心。
# 安装
-
1. 搭建虚拟环境 Linux /// windows
$ sudo easy_install virtualenv
Ubantu
$ sudo apt-get install python-virtualenv
虚拟环境
mkvirtualenv # 创建虚拟环境
rmvirtualenv # 删除虚拟环境
workon # 进入虚拟环境、查看所有虚拟环境
deactivate # 退出虚拟环境
pip
install # 安装依赖包
pip uninstall # 卸载依赖包
pip list # 查看已安装的依赖包
pip freeze # 冻结当前环境的依赖包
-
2.创建虚拟环境
mkvirtualenv flask -p python3
-
3. 安装Flask
pip install flask
初始程序Hello World!
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True)
那么,这段代码做了什么?
首先,我们导入了 Flask 类。这个类的实例将会是我们的 WSGI 应用程序。
接下来,我们创建一个该类的实例,第一个参数是应用模块或者包的名称。 如果你使用单一的模块(如本例),你应该使用 __name__ ,因为模块的名称将会因其作为单独应用启动还是作为模块导入而有不同( 也即是 ‘__main__’ 或实际的导入名)。这是必须的,这样 Flask 才知道到哪去找模板、静态文件等等。详情见 Flask 的文档。
然后,我们使用 route() 装饰器告诉 Flask 什么样的URL 能触发我们的函数。
这个函数的名字也在生成 URL 时被特定的函数采用,这个函数返回我们想要显示在用户浏览器中的信息。
最后我们用 run() 函数来让应用运行在本地服务器上。 其中 if __name__ == ‘__main__’: 确保服务器只会在该脚本被 Python 解释器直接执行的时候才会运行,而不是作为模块导入的时候。
参数
- Flask对象的初始化参数 app = Flask(参数)-
应用程序配置参数
-
app.run()运行参数
1. Flask对象的初始化参数
app = Flask(参数)
import_name
Flask程序所在的包(模块),传 __name__ 就可以其可以决定 Flask 在访问静态文件时查找的路径
static_url_path
静态文件访问路径,可以不传,默认为:/ + static_folder
static_folder
静态文件存储的文件夹,可以不传,默认为 static
template_folder
模板文件存储的文件夹,可以不传,默认为 templates
默认参数情况下
app = Flask(__name__)
文件目录
----
|---static
| |--- 1.png
|---helloworld.py
访问 127.0.0.1:5000/static/1.png 就可以访问到图片
修改参数的情况下
app = Flask(__name__, static_url_path='/url_path_param',
static_folder='folder_param')
文件目录
----
|---folder_param # 此处目录名变化
| |--- 1.png
|---helloworld.py
访问127.0.0.1:5000/url_path_param/1.png才可以访问到图片
2. 应用程序配置参数
应用程序配置参数设置的是一个Web应用工程的相关信息,如数据库的连接信息、
日志的配置信息、
自定义的配置信息等
创建一个config.py文件,集中管理项目的所有配置信息。
(对应的是django中的setting.py)
使用
Flask将配置信息保存到了app.config属性中,该属性可以按照字典类型进行操作。
读取
app.config.get(name)
app.config[name]
设置
1. 从配置对象中加载
class DefaultConfig(object):
"""默认配置"""
SECRET_KEY = 'TPmi4aLWRbyVq8zu9v82dWYW1'
app = Flask(__name__)
app.config.from_object(DefaultConfig)
@app.route("/")
def index():
print(app.config['SECRET_KEY'])
return "hello world"
2.从配置文件中加载
新建一个配置文件setting.py
SECRET_KEY = ‘TPmi4aLWRbyVq8zu9v82dWYW1’
DEBUG = Ture
在Flask程序中
app = Flask(__name__)
# app.config.from_pyfile('setting.py')
app.config.from_pyfile('setting.ini')
@app.route("/")
def index():
print(app.config['SECRET_KEY'])
return "hello world"
3.从环境变量中加载
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。 环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。
通俗的理解,环境变量就是我们设置在操作系统中,由操作系统代为保存的变量值
在Linux系统中设置和读取环境变量的方式如下:
export 变量名=变量值 # 设置
echo $变量名 # 读取
# 例如
export abc=python
echo abc
Flask使用环境变量加载配置的本质是通过环境变量值找到配置文件,再读取配置文件的信息,其使用方式为
app.config.from_envvar(‘环境变量名’)
环境变量的值为配置文件的绝对路径
先在终端中执行如下命令
export PROJECT_SETTING=’~/setting.py’
export FLASK_ENV = ‘/home/python/Desktop/demo/config.ini’
再运行如下代码
app = Flask(__name__)
# 用这个比较安全 仅存放敏感信息
app.config.from_envvar('PROJECT_SETTING', silent=True)
# 一般配置放在这里
app.config.from_object(config_dict['dev'])
@app.route("/")
def index():
print(app.config['SECRET_KEY'])
return "hello world"
-
关于silent的说明:
表示系统环境变量中没有设置相应值时是否抛出异常
- False 表示不安静的处理,没有值时报错通知,默认为False
- True 表示安静的处理,即时没有值也让Flask正常的运行下去
在pycharm中配置 xxx = (copy xx path)
3 app.run 参数
可以指定运行的主机IP地址,端口,是否开启调试模式
app.run(host=“0.0.0.0”, port=5000, debug = True)
蓝图
在Flask中,使用蓝图Blueprint来分模块组织管理。
蓝图实际可以理解为是一个存储一组视图方法的容器对象,其具有如下特点:
- 一个应用可以具有多个Blueprint
- 可以将一个Blueprint注册到任何一个未使用的URL下比如 “/user”、“/goods”
- Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的在一个应用初始化时,就应该要注册需要使用的Blueprint
但是一个Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中。
使用方式
使用蓝图可以分为三个步骤:
文件:
--------- project # 工程目录
|------ main.py # 启动文件
|------ user #用户蓝图
| |--- __init__.py # 此处创建蓝图对象
| |--- passport.py
| |--- profile.py
| |--- ...
|
|------ goods # 商品蓝图
| |--- __init__.py
| |--- ...
|...
-
创建蓝图对象
创建个包,在__init__.py中,最下面要
导入视图 不然flsk找不到视图
user_bp=Blueprint('user',__name__)
from . import views
- 在这个蓝图对象上进行操作,注册路由,指定静态文件夹,注册模版过滤器(工厂里)
@user_bp.route('/')
def user_profile():
return 'user_profile'
- 在应用对象上注册这个蓝图对象(url_prefix参数是设置工厂里)
app.register_blueprint(user_bp,url_prefix='/user')
其他
-
蓝图内部静态文件
和应用对象不同,蓝图对象创建时不会默认注册静态目录的路由。需要我们在 创建时指定 static_folder 参数。
下面的示例将蓝图所在目录下的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’) -
蓝图内部模板目录
蓝图对象默认的模板目录为系统的模版目录,可以在创建蓝图对象时使用 template_folder 关键字参数设置模板目录
admin = Blueprint(‘admin’,__name__,template_folder=‘my_templates’)
请求与相应
请求
在视图编写中需要读取客户端请求携带的数据时,如何才能正确的取出数据呢?
请求携带的数据可能出现在HTTP报文中的不同位置,需要使用不同的方法来获取参数。
1. URL路径参数(动态路由)
例如,有一个请求访问的接口地址为/users/123,其中123实际上为具体的请求参数,表明请求123号用户的信息。此时如何从url中提取出123的数据?
Flask不同于Django直接在定义路由时编写正则表达式的方式,而是采用转换器语法:
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return 'hello user {}'.format(user_id)
此处的<>即是一个转换器,默认为字符串类型,即将该位置的数据以字符串格式进行匹配、并以字符串为数据类型类型、 user_id为参数名传入视图。
Flask也提供其他类型的转换器
DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'path': PathConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter, }
自定义转换器
Flask内置的转换器无法满足需求时,需要自定义转换器。
定义方法
- 创建converters.py 创建自定义转换器类,保存匹配时的正则表达式
from werkzeug.routing import BaseConverter
class MobileConverter(BaseConverter):
"""
手机号自定义转换器
"""
regex = r'1[3-9]\d{9}'
注:regex是固定的
- 将自定义的转换器告知Flask应用
# 在app_factory.py中 先于注册使用该自定义转换器的蓝图注册该转换器。
app = Flask(__name__)
# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: mobile
app.url_map.converters['mobile'] = MobileConverter
- 在使用转换器的地方定义使用
@app.route('/sms_codes/')
def send_sms_code(mob_num):
return 'send sms code to {}'.format(mob_num)
2. 其他参数
如果想要获取其他地方传递的参数,可以通过Flask提供的request对象来读取。
from flask improt request
不同位置的参数都存放在request的不同属性中
属性 | 说明 | 类型 |
---|---|---|
data | 记录请求的数据,并转换为字符串 | * |
form | 记录请求中的表单数据 | MultiDict |
args | 记录请求中的查询参数 | MultiDict |
cookies | 记录请求中的cookie信息 | Dict |
headers | 记录请求中的报文头 | EnvironHeaders |
method | 记录请求使用的HTTP方法 | GET/POST |
url | 记录请求的URL地址 | string |
files | 记录请求上传的文件 | * |
例如 想要获取请求/articles?channel_id=1中channel_id的参数,可以按如下方式使用:
from flask import request
@app.route('/articles')
def get_articles():
channel_id = request.args.get('channel_id')
return 'you wanna get articles of channel {}'.format(channel_id)
##上传图片
客户端上传图片到服务器,并保存到服务器中
from flask import request
@app.route('/upload', methods=['POST'])
def upload_file():
f = request.files['pic']
# with open('./demo.png', 'wb') as new_file:
# new_file.write(f.read())
f.save('./demo.png')
return 'ok'
-
flask的request和django的的区别:
数 flask属性 django属性 询参数 args GET headers META -表单 form POST -json data body
响应
-
- 返回模板
-
- 返回JSON
-
- 重定向
from flask import render_template
# 返回模板
@app.route('/')
def index():
mstr = 'Hello world'
mint = 10
return render_template('index.html', my_str=mstr, my_int=mint)
from flask import jsonify
# 返回json
@app.route('/json')
def demo_json():
json_dict = {
"user_id": 1,
"user_name": "lily"
}
return jsonify(json_dict)
# return json.dumps(json_dict)
# 区别 content-type 一个是txt一个是json
from flask import redirect
# 重定向
@app.route('/redirect')
def demo_redirect():
return redirect('http://www.baidu.com')
其他 (自定义状态码和响应头)
- 元祖方式
可以返回一个元组,这样的元组必须是 (response, status, headers) 的形式,且至少包含一个元素。 status 值会覆盖状态代码, headers 可以是一个列表或字典,作为额外的消息标头值。
@app.route('/demo4')
def demo4():
# return '状态码为 200', 200
# return '状态码为 200', 200, [('name', 'lily')]
return '状态码为 200', 200, {'name': 'lily'}
-
make_response方式
@app.route(’/response’)
def response_demo():
resp = make_response(‘make response测试’)
resp.headers[‘name’] = “lily”
resp.status = “404 NOT FOUND”
return resp
Cookie与Session
Cookie
views.py里 工厂里 都可以
- 设置
from flask import Flask, make_response
@app.route('/cookie')
def set_cookie():
response_cookie = make_response('this is cookie')
response_cookie.set_cookie('username', 'lily',max_age=3600)
# 删除cookie
# response_cookie.delete_cookie('username')
return resp
-
读取
cookie_username = request.cookies.get(‘username’)
##Session
先在setting.py/config.py中设置SECRET_KEY 字符串
SECRET_KEY = ‘fvrw4utw%¥h9zg5fg4^gh24’
from flask import session
@app.route('/set_session')
def set_session():
session['username'] = 'laowang'
# 读取session
# username = session.get('username')
return 'set session ok'
# 异常处理
- abort 方法
抛出一个给定状态代码的 HTTPException 或者 指定响应,例如想要用一个页面未找到异常来终止请求,你可以调用 abort(404)。
- 参数 code – HTTP的错误状态码
-
捕获错误
-
errorhandler 装饰器
注册一个错误处理程序,当程序抛出指定错误状态码的时候,就会调用该装饰器所装饰的方法
参数 code_or_exception – HTTP的错误状态码或指定异常
-
@app.errorhandler(500)
def internal_server_error(e):
return '没东西'
# 捕获特定异常
@app.errorhandler(MyError)
def My_Error(e):
return '除数不能为0'
请求钩子
###控制反转(Inversion of Control,缩写为IoC)
在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:
- 在请求开始时,建立数据库连接;
- 在请求开始时,根据需求进行权限校验;
- 在请求结束时,指定数据的交互格式;
为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。
(参考vue的生命周期django的中间键)
请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子:
-
before_first_request
在处理第一个请求前执行
-
before_request
在每次请求前执行
如果在某修饰的函数中返回了一个响应,视图函数将不再被调用 -
after_request
如果没有抛出错误,在每次请求后执行
接受一个参数:视图函数作出的响应
在此函数中可以对响应值在返回之前做最后一步修改处理
需要将参数中的响应在此参数中进行返回 -
teardown_request
在每次请求后执行
接受一个参数:错误信息,如果有相关错误抛出
from flask import Flask
from flask import abort
app = Flask(__name__)
# 在第一次请求之前调用,可以在此方法内部做一些初始化操作
@app.before_first_request
def before_first_request():
print("1-------------before_first_request")
# 在每一次请求之前调用,这时候已经有请求了,可能在这个方法里面做请求的校验
# 如果请求的校验不成功,可以直接在此方法中进行响应,直接return之后那么就不会执行视图函数
@app.before_request
def before_request():
print("2-----------before_request")
# if 请求不符合条件:
# return "传入参数错误!"
# 在执行完视图函数之后会调用,并且会把视图函数所生成的响应传入,可以在此方法中对响应做最后一步统一的处理
@app.after_request
def after_request(response):
print("3-------------after_request")
response.headers["Content-Type"] = "application/json"
return response
# 请每一次请求之后都会调用,会接受一个参数,参数是服务器出现的错误信息
@app.teardown_request
def teardown_request(response):
print("4---------------teardown_request")
@app.route('/')
def index():
return 'index'
if __name__ == '__main__':
app.run(debug=True)
after_request和teardown_request必须接受response
前者有报错不执行,接收的是视图返回的响应作为参数并返回响应
后者有异常依然执行,必须接受异常信息作为参数
这里的异常不该是应用(手动抛出的)异常而应该是服务器内部抛出的异常 500+
Context (上下文)
上下文:即语境,语意,在程序中可以理解为在代码执行到某一时刻时,根据之前代码所做的操作以及下文即将要执行的逻辑,可以决定在当前时刻下可以使用到的变量,或者可以完成的事情。
Flask中有两种上下文,请求上下文和应用上下文
Flask中上下文对象:相当于一个容器,保存了 Flask 程序运行过程中的一些信息。
1. 请求上下文(request context)
思考:在视图函数中,如何取到当前请求的相关数据?比如:请求地址,请求方式,cookie等等
在 flask 中,可以直接在视图函数中使用 request 这个对象进行获取相关数据,而 request 就是请求上下文的对象,保存了当前本次请求的相关数据,请求上下文对象有:request、session
- request
封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get(‘user’),获取的是get请求的参数。
- session
用来记录请求会话中的信息,针对的是用户信息。举例:session[‘name’] = user.id,可以记录用户信息。还可以通过session.get(‘name’)获取用户信息。
2 应用上下文(application context)
它的字面意思是 应用上下文,但它不是一直存在的,它只是request context 中的一个对 app 的代理(人),所谓local proxy。它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。
应用上下文对象有:current_app,g ---- 全局的 当次全局的
-
current_app
-
其实就是之前用的app.config.get(‘SECRET_KEY’) 现在用作current.config.get(‘SECRET_KEY’)
应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name打印当前app的名称,也可以在current_app中存储一些变量,例如:应用的启动脚本是哪个文件,启动时指定了哪些参数
加载了哪些配置文件,导入了哪些配置
连了哪个数据库
有哪些public的工具类、常量
应用跑再哪个机器上,IP多少,内存多大
创建current_app_demo.py
在views.py里面 from flask import current_app
current_app 就是当前运行的flask app,在代码不方便直接操作flask的app对象时,可以操作current_app就等价于操作flask app对象
Q: 什么时候不能访问app呢?
- 容易发生循环倒包的问题的时候。
- g对象
g 作为 flask 程序全局的一个临时变量,充当中间媒介的作用,我们可以通过它在一次请求调用的多个函数间传递一些数据。每次请求都会重设这个变量。
- g对象与请求钩子的综合案例
from flask import Flask
# 手动构建用户认证机制
# 需求:项目首页任何权限可以访问,个人信息页必须登录才能看
# 实现:1.在所有请求执行前尝试获取用户信息,使用请求钩子before_request,给g.user_id赋值
# 是否允许进入视图。添加装饰器
@app.before_request
def authentication():
# token == header.payload.singnature
# request.headers.get('Authentication')
@app.route('/')
def index():
return 'index'
# 个人信息页
@app.route('/profile')
def profile_page():
return 'uesr profile page'
if __name__=='__main__':
app.run()
Q:待完成—
-
app_context 与 request_context
-
不太明白,回头看文档
-
上面的四个都需要上下文语境,要有访问请求才能用
-
手动推送上下文,后就可以用了
with app.app_context():
print(current_app.config.get('DEBUG'))
environ = {'wsgi.version':(1,0),'wsgi.input':'','REQUEST_METHOD':'GET','PATH_INFO':'/','SERVER_NAME':'server', 'wsgi.url_scheme':'http', 'SERVER_PORT': '80'} # 模拟解析客户端请求之后的wsgi字典数据
with app.request_context(environ): # 借助with语句用request_context创建请求上下文
print(request.path)
Flask-RESTful
是用于快速构建REST API的Flask扩展。
##1 安装
pip install flask-restful
##2 应用
# 创建一个包api 在__init__.py中
from flask import Blueprint
api_bp = Blueprint('api',__name__,url_prefix='/api')
from . import views
# 之前不用RESTful的时候
# 在views中
from . import api_bp
from flask.views import MethodView,View
class IndexView(MethodView):
def get(self):
return {'title':'lily'}
def post(self):
return 'post'
# 注册路由 起名是避免端点重名
api_bp.add_url_rule('/',view_func=IndexView.as_view('index'))
# 用REST
from flask_restful import Resource,Api
api = Api(api_bp)
# 创建api对象 为了注册路由规则
# api.add_resource(集成Resource的类的名字,路径)
class IndexResource(Resource):
def get(self):
return {'title':'lily'}
api.add_resource(IndexResource,'/r/')
# 返回值的格式是json
##3 装饰器
def dec1(view):
def wrapper(*args,**kwargs):
print('1')
return view(*args,**kwargs)
def dec2(view):
def wrapper(*args,**kwargs):
print('2')
return view(*args,**kwargs)
# 在Resource中
class IndexResource(Resource):
method_decorators = {'get':[dec1,dec2],'post':[dec1]}
def get(self):
print('view')
return {'title':'lily'}
api.add_resource(IndexResource,'/r/')
结果是2- 1- view
#Q:django是用的继承, 这里可不可以 以及为什么不用继承呢
# 可以 只是django自己写好了,这边没写就用装饰器了,想写就去写
序列化器
Flask-RESTful 提供了marshal工具,用来帮助我们将数据序列化为特定格式的字典数据,以便作为视图的返回值。
from flask_restful import Resource, fields, marshal_with
resource_fields = {
'name': fields.String,
'address': fields.String,
'user_id': fields.Integer,
'parents':fields.Nested({
'name':fields.String,
'age':fields.Integer
})
}
class UserResource(Resource):
@marshal_with(resource_fields, envelope='resource')
def get(self, **kwargs):
user = User()
return user()
# 不使用装饰器使用marshal
class UserResource1(Resource):
def get(self):
user = User()
return marshal(user, resource_fields)
# 对象 序列化器 envelope 返回的key
api.add_resource(UserResource,'/users/')
api.add_resource(UserResource1,'/users1/')
反序列化
Flask-RESTful 提供了RequestParser类,用来帮助我们检验和转换请求数据。
使用步骤
-
创建RequestParser对象
-
向RequestParser对象中添加需要检验或转换的参数声明
-
使用parse_args()方法启动检验处理
-
检验之后从检验结果中获取参数时可按照字典操作或对象属性操作
参数
-
required = Ture 是否必传
-
help=‘错误提示文本’
-
action
-
描述对于请求参数中出现多个同名参数时的处理方式
action=‘store’ 保留出现的第一个, 默认
action=‘append’ 以列表追加保存所有同名参数的值
-
-
type
Flask-RESTful提供
检验类型方法在flask_restful.inputs模块中
-
url
-
regex(指定正则表达式)
from flask_restful import inputs rp.add_argument('a', type=inputs.regex(r'^\d{2}$'))
int_range(low ,high) 整数范围
rp.add_argument(‘a’, type=inputs.int_range(1, 10))
-
natural 自然数0、1、2、3…
-
positive 正整数 1、2、3…
-
boolean
-
自定义
-
-
location
描述参数应该在请求数据中出现的位置
# Look only in the POST body parser.add_argument('name', type=int, location='form') # Look only in the querystring parser.add_argument('PageSize', type=int, location='args') # From the request headers parser.add_argument('User-Agent', location='headers') # From http cookies parser.add_argument('session_id', location='cookies') # From json parser.add_argument('user_id', location='json') # From file uploads parser.add_argument('picture', location='files')
也可指明多个位置
parser.add_argument('text', location=['headers', 'json'])
def post(self):
# 接收
#params = json.loads(request.data.decode())
from flask_restful import reqparse
# 反序列化
parser = reqparse.RequestParser()
# 验证
parser.add_argument('name', type=string, help='错误提示文本', location='args')
parser.add_argument('age')
# 接收
args = parser.parse_args()
定制返回的JSON格式
Flask-RESTful的Api对象提供了一个representation的装饰器,允许定制返回数据的呈现格式
app= Flask(__name__)
api = Api(app)
class HelloWorldResource(Resource):
def get(self):
return {'get':'ok'}
@api.representation('application/json')
def output_json(data, code, headers=None):
"""Makes a Flask response with a JSON encoded body"""
# 此处为自己添加***************
if 'message' not in data:
data = {
'message': 'OK',
'data': data
}
# **************************
settings = current_app.config.get('RESTFUL_JSON', {})
# If we're in debug mode, and the indent is not set, we set it to a
# reasonable value here. Note that this won't override any existing value
# that was set. We also set the "sort_keys" value.
if current_app.debug:
settings.setdefault('indent', 4)
settings.setdefault('sort_keys', not PY3)
# always end the json dumps with a new line
# see https://github.com/mitsuhiko/flask/pull/1262
dumped = dumps(data, **settings) + "\n"
resp = make_response(dumped, code)
resp.headers.extend(headers or {})
return resp
实操流程 项目从开始到放弃
- 创建Flask项目
—>
- 创建main.py (启动文件)
—>
from app_factory import create_app
from config import DevConfig
if __name__ == '__main__':
app = create_app(DevConfig)
app.run()
创建app_factory.py和config.py
—>
- 封装创建对象工厂和配置的类
app_fartory.py — # app.config.get(‘配置项’)
from flask import Flask
def create_app(config):
app = Flask(__name__)
app.config.from_object(config)
return app
config.py
class BaseConfig(object):
# KEY都大写
DEBUG = True
class DevConfig(BaseConfig):
pass
class ProdConfig(BaseConfig):
DEBUG = False
---->
-
创建子应用(蓝图)和视图View MethodView
-
###蓝图
-
新建一个项目–main.py—
app_factory.py—config.py—去工厂注册config
-
- 新建一个包news ,users
-
2.news/__init__.py
from flask import Blueprint
-
-
user_bp=Blueprint(‘user’,name)
from . import views
</pre>
- 3.news/views.py 这时候注册路由就用蓝图来注册了
<pre class="prettyprint lang-javascript">
from . import user_bp
@user_bp.route('/login/')
def login():
return 'login'
</pre>
- 4.去工厂注册蓝图 app_factory.py
<pre class="prettyprint lang-javascript">app.register_blueprint(user_bp)</pre>
<br>
- ###视图
# Demo-View
from flask import Flask
from flask.views import View,MethodView
app = Flask(__name__)
class DemoView(View):
methods = ['GET','POST']
# 所有的请求方式都来到这个方法 想区分内部要去进行判断 这个类一般不用的
def despatch_request(self):
return 'OK'
app.add_url_rule('/demo1/',view_func=DemoView.as_view('demoview'))
if __name__='__main__':
print(app.url_map)
app.run(debug=True)
</pre>
---
- MethodView
# Demo-MethodView
from flask import Flask
from flask.views import View,MethodView
app = Flask(__name__)
class DemoMethodView(MethodView):
methods = ['GET','POST']
def get(self):
return 'get~'
def post(self):
return 'post~'
app.add_url_rule('/demo1/',view_func=DemoMethodView.as_view('methoddemoview'))
if __name__='__main__':
print(app.url_map)
app.run(debug=True)
</pre>
View和MethodView的区别:
待完成—
—>
路由内部正则或者接收参数需要用到转换器converters
需要自定义转换器时,创建converters.py文件
在(工厂中)注册蓝图之前 要先注册转换器
from converters import MobileConverter
app.url_map.converters['mobile']=MobileConverter
然后视图就可以正常使用了
@news_bp.route(//)
def hello(Mob):
return Mob