Flask学习
Flask 中文文档地址
https://dormousehole.readthedocs.io/en/latest/index.html
一、快速入门
示例:最简单的应用
from flask import Flask
app = Flask(__name__) # 创建flask的app
@app.route("/") #创建视图函数,利用装饰器可以配置路由
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
二、知识点
1. 配置文件
代码如下(示例):flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
从配置对象中加载(常用)
{
'DEBUG': get_debug_flag(default=False), 是否开启Debug模式
'TESTING': False, 是否开启测试模式
'PROPAGATE_EXCEPTIONS': None,
'PRESERVE_CONTEXT_ON_EXCEPTION': None,
'SECRET_KEY': None,
'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
'USE_X_SENDFILE': False,
'LOGGER_NAME': None,
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None,
'APPLICATION_ROOT': None,
'SESSION_COOKIE_NAME': 'session',
'SESSION_COOKIE_DOMAIN': None,
'SESSION_COOKIE_PATH': None,
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'SESSION_REFRESH_EACH_REQUEST': True,
'MAX_CONTENT_LENGTH': None,
'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12),
'TRAP_BAD_REQUEST_ERRORS': False,
'TRAP_HTTP_EXCEPTIONS': False,
'EXPLAIN_TEMPLATE_LOADING': False,
'PREFERRED_URL_SCHEME': 'http',
'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True,
'JSONIFY_PRETTYPRINT_REGULAR': True,
'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None,
}
方式一:
app.config['DEBUG'] = True
PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
方式二:
app.config.from_pyfile("python文件名称")
如:
settings.py
DEBUG = True
app.config.from_pyfile("settings.py")
app.config.from_envvar("环境变量名称")
环境变量的值为python文件名称名称,内部调用from_pyfile方法
app.config.from_json("json文件名称")
JSON文件名称,必须是json格式,因为内部会执行json.loads
app.config.from_mapping({'DEBUG':True})
字典格式
**方式三:**
创建mysettings.py文件
app.config.from_object("mysettings")
app.config.from_object('mysettings.TestingConfig')
mysettings.py
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite://:memory:'
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
PS: 从sys.path中已经存在路径开始写
2. 路由
使用 route() 装饰器来把函数绑定到 URL:
from markupsafe import escape
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return f'User {escape(username)}'
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return f'Post {post_id}'
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# show the subpath after /path/
return f'Subpath {escape(subpath)}'
HTTP 方法
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
3. 视图
#CBV视图
from flask import Flask,url_for,views
#-----------------------------------------------------
app=Flask(__name__) #装饰器
def auth(func):
print('我在上面')
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
#--------------------------------------------------------
class IndexView(views.MethodView): #CBV视图
methods=['GET'] #允许的http请求方法(改CBV只允许GET方法)
decorators = [auth,] #每次请求过来都加auth装饰器
def get(self):
return 'Index.GET'
def post(self):
return 'Index.POST'
app.add_url_rule('/index/',view_func=IndexView.as_view(name='name1')) #(name='name1'反向生成url别名
if __name__ == '__main__':
app.run()
4. 模板
Jinja2文档 http://docs.jinkan.org/docs/jinja2/
<title>{% block title %}{% endblock %}</title>
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
5. 蓝图
蓝图的基本概念是:在蓝图被注册到应用之后,所要执行的操作的集合。当分配请求 时, Flask 会把蓝图和视图函数关联起来,并生成两个端点之前的 URL 。
from flask import Blueprint, render_template, abort
from jinja2 import TemplateNotFound
simple_page = Blueprint('simple_page', __name__,
template_folder='templates')
@simple_page.route('/', defaults={'page': 'index'})
@simple_page.route('/<page>')
def show(page):
try:
return render_template(f'pages/{page}.html')
except TemplateNotFound:
abort(404)
注册蓝图
from flask import Flask
from yourapplication.simple_page import simple_page
app = Flask(__name__)
app.register_blueprint(simple_page)
6. 中间件
请求扩展
① before_request
类比django中间件中的process_request,在请求收到之前绑定一个函数做一些事情
#基于它做用户登录认证
@app.before_request
def process_request(*args,**kwargs):
if request.path == '/login':
return None
user = session.get('user_info')
if user:
return None
return redirect('/login')
② after_request
类比django中间件中的process_response,每一个请求之后绑定一个函数,如果请求没有异常
@app.after_request
def process_response1(response):
print('process_response1 走了')
return response
③ before_first_request
第一次请求时,跟浏览器无关
@app.before_first_request
def first():
pass
④ teardown_request
每一个请求之后绑定一个函数,即使遇到了异常
@app.teardown_request
def ter(e):
pass
⑤ errorhandler
路径不存在时404,服务器内部错误500
Copy@app.errorhandler(404)
def error_404(arg):
return "404错误了"
⑥ template_global
标签
Copy@app.template_global()
def sb(a1, a2):
return a1 + a2
#{{sb(1,2)}}
⑦ template_filter
过滤器
Copy@app.template_filter()
def db(a1, a2, a3):
return a1 + a2 + a3
#{{ 1|db(2,3)}}
总结
- 重点掌握before_request和after_request
- 注意有多个的情况,执行顺序
- before_request请求拦截后(也就是有return值),response所有都执行
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World!'
# 模拟中间件
class Md(object):
def __init__(self, old_wsgi_app):
self.old_wsgi_app = old_wsgi_app
def __call__(self, environ, start_response):
print('开始之前')
ret = self.old_wsgi_app(environ, start_response)
print('结束之后')
return ret
if __name__ == '__main__':
# 1.我们发现当执行app.run方法的时候,最终执行run_simple,最后执行app(),也就是在执行app.__call__方法
# 2.在__call__里面,执行的是self.wsgi_app().那我们希望在执行他本身的wsgi之前做点事情。
# 3.所以我们先用Md类中__init__,保存之前的wsgi,然后我们用将app.wsgi转化成Md的对象。
# 4.那执行新的的app.wsgi_app,就是执行Md的__call__方法。
# 5.把原来的wsgi_app替换为自定义的,
app.wsgi_app = Md(app.wsgi_app)
app.run()
7. 相关组件
Flask-SQLalchemy:操作数据库;
Flask-migrate:管理迁移数据库;
Flask-Mail:邮件;
Flask-WTF:表单;
Flask-Bable:提供国际化和本地化支持,翻译;
Flask-script:插入脚本;
Flask-Login:认证用户状态;
Flask-OpenID:认证;
Flask-RESTful:开发REST API的工具;
Flask-Bootstrap:集成前端Twitter Bootstrap框架;
Flask-Moment:本地化日期和时间;
Flask-Admin:简单而可扩展的管理接口的框架
扩展列表:http://flask.pocoo.org/extensions/
中文文档(http://docs.jinkan.org/docs/flask/)
英文文档(http://flask.pocoo.org/docs/0.11/)