python高级之Flask框架

目录:

  • Flask基本使用
  • Flask配置文件
  • Flask路由系统
  • Flask模版
  • Flask请求与响应
  • Flask之Session
  • Flask之蓝图
  • Flask之message
  • 中间件
  • Flask插件

一、Flask基本使用

1、flask简介

lask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

2、flask安装

pip3 install flask

3、flask之werkaeug

from werkzeug.wrappers import Request, Response

@Request.application
def hello(request):
return Response(‘Hello World!‘)

if __name__ == ‘__main__‘:
from werkzeug.serving import run_simple
run_simple(‘localhost‘, 4000, hello)

1 from werkzeug.wrappers import Request, Response
2
3 @Request.application
4 def hello(request):
5     return Response(‘Hello World!‘)
6
7 if __name__ == ‘__main__‘:
8     from werkzeug.serving import run_simple
9     run_simple(‘localhost‘, 4000, hello)

4、flask基本使用

from flask import Flask
app = Flask(__name__)

@app.route(‘/‘)
def hello_world():
return ‘Hello World!‘

if __name__ == ‘__main__‘:
app.run()

二、Flask配置文件

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,
}

 1 {
 2         ‘DEBUG‘:                                get_debug_flag(default=False),  是否开启Debug模式
 3         ‘TESTING‘:                              False,                          是否开启测试模式
 4         ‘PROPAGATE_EXCEPTIONS‘:                 None,
 5         ‘PRESERVE_CONTEXT_ON_EXCEPTION‘:        None,
 6         ‘SECRET_KEY‘:                           None,
 7         ‘PERMANENT_SESSION_LIFETIME‘:           timedelta(days=31),
 8         ‘USE_X_SENDFILE‘:                       False,
 9         ‘LOGGER_NAME‘:                          None,
10         ‘LOGGER_HANDLER_POLICY‘:               ‘always‘,
11         ‘SERVER_NAME‘:                          None,
12         ‘APPLICATION_ROOT‘:                     None,
13         ‘SESSION_COOKIE_NAME‘:                  ‘session‘,
14         ‘SESSION_COOKIE_DOMAIN‘:                None,
15         ‘SESSION_COOKIE_PATH‘:                  None,
16         ‘SESSION_COOKIE_HTTPONLY‘:              True,
17         ‘SESSION_COOKIE_SECURE‘:                False,
18         ‘SESSION_REFRESH_EACH_REQUEST‘:         True,
19         ‘MAX_CONTENT_LENGTH‘:                   None,
20         ‘SEND_FILE_MAX_AGE_DEFAULT‘:            timedelta(hours=12),
21         ‘TRAP_BAD_REQUEST_ERRORS‘:              False,
22         ‘TRAP_HTTP_EXCEPTIONS‘:                 False,
23         ‘EXPLAIN_TEMPLATE_LOADING‘:             False,
24         ‘PREFERRED_URL_SCHEME‘:                 ‘http‘,
25         ‘JSON_AS_ASCII‘:                        True,
26         ‘JSON_SORT_KEYS‘:                       True,
27         ‘JSONIFY_PRETTYPRINT_REGULAR‘:          True,
28         ‘JSONIFY_MIMETYPE‘:                     ‘application/json‘,
29         ‘TEMPLATES_AUTO_RELOAD‘:                None,
30     }

1、调用方式

方式一:
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})
字典格式

app.config.from_object("python类或类的路径")

app.config.from_object(‘pro_flask.settings.TestingConfig‘)

settings.py

class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = ‘sqlite://:memory:‘

class ProductionConfig(Config):
DATABASE_URI = ‘mysql://[email protected]/foo‘

class DevelopmentConfig(Config):
DEBUG = True

class TestingConfig(Config):
TESTING = True

 1 方式一:
 2     app.config[‘DEBUG‘] = True
 3
 4     PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
 5
 6 方式二:
 7     app.config.from_pyfile("python文件名称")
 8         如:
 9             settings.py
10                 DEBUG = True
11
12             app.config.from_pyfile("settings.py")
13
14     app.config.from_envvar("环境变量名称")
15         环境变量的值为python文件名称名称,内部调用from_pyfile方法
16
17
18     app.config.from_json("json文件名称")
19         JSON文件名称,必须是json格式,因为内部会执行json.loads
20
21     app.config.from_mapping({‘DEBUG‘:True})
22         字典格式
23
24     app.config.from_object("python类或类的路径")
25
26         app.config.from_object(‘pro_flask.settings.TestingConfig‘)
27
28         settings.py
29
30             class Config(object):
31                 DEBUG = False
32                 TESTING = False
33                 DATABASE_URI = ‘sqlite://:memory:‘
34
35             class ProductionConfig(Config):
36                 DATABASE_URI = ‘mysql://[email protected]/foo‘
37
38             class DevelopmentConfig(Config):
39                 DEBUG = True
40
41             class TestingConfig(Config):
42                 TESTING = True

 PS: 从sys.path中已经存在路径开始写

 PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录

三、Flask路由系统

1、基本路由系统

  • @app.route(‘/user/<username>‘)
  • @app.route(‘/post/<int:post_id>‘)
  • @app.route(‘/post/<float:post_id>‘)
  • @app.route(‘/post/<path:path>‘)
  • @app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])

常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:

DEFAULT_CONVERTERS = {

    ‘default‘:          UnicodeConverter,

    ‘string‘:           UnicodeConverter,

    ‘any‘:              AnyConverter,

    ‘path‘:             PathConverter,

    ‘int‘:              IntegerConverter,

    ‘float‘:            FloatConverter,

    ‘uuid‘:             UUIDConverter,

}

2、注册路由原理

def auth(func):
def inner(*args, **kwargs):
print(‘before‘)
result = func(*args, **kwargs)
print(‘after‘)
return result

return inner

@app.route(‘/index.html‘,methods=[‘GET‘,‘POST‘],endpoint=‘index‘)
@auth
def index():
return ‘Index‘

def index():
return "Index"

self.add_url_rule(rule=‘/index.html‘, endpoint="index", view_func=index, methods=["GET","POST"])
or
app.add_url_rule(rule=‘/index.html‘, endpoint="index", view_func=index, methods=["GET","POST"])
app.view_functions[‘index‘] = index


def auth(func):
def inner(*args, **kwargs):
print(‘before‘)
result = func(*args, **kwargs)
print(‘after‘)
return result

return inner

class IndexView(views.View):
methods = [‘GET‘]
decorators = [auth, ]

def dispatch_request(self):
print(‘Index‘)
return ‘Index!‘

app.add_url_rule(‘/index‘, view_func=IndexView.as_view(name=‘index‘)) # name=endpoint

class IndexView(views.MethodView):
methods = [‘GET‘]
decorators = [auth, ]

def get(self):
return ‘Index.GET‘

def post(self):
return ‘Index.POST‘

app.add_url_rule(‘/index‘, view_func=IndexView.as_view(name=‘index‘)) # name=endpoint

@app.route和app.add_url_rule参数:
rule, URL规则
view_func, 视图函数名称
defaults=None, 默认值,当URL中无参数,函数需要参数时,使用defaults={‘k‘:‘v‘}为函数提供参数
endpoint=None, 名称,用于反向生成URL,即: url_for(‘名称‘)
methods=None, 允许的请求方式,如:["GET","POST"]

strict_slashes=None, 对URL最后的 / 符号是否严格要求,
如:
@app.route(‘/index‘,strict_slashes=False),
访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
@app.route(‘/index‘,strict_slashes=True)
仅访问 http://www.xx.com/index
redirect_to=None, 重定向到指定地址
如:
@app.route(‘/index/<int:nid>‘, redirect_to=‘/home/<nid>‘)

def func(adapter, nid):
return "/home/888"
@app.route(‘/index/<int:nid>‘, redirect_to=func)
subdomain=None, 子域名访问
from flask import Flask, views, url_for

app = Flask(import_name=__name__)
app.config[‘SERVER_NAME‘] = ‘wupeiqi.com:5000‘

@app.route("/", subdomain="admin")
def static_index():
"""Flask supports static subdomains
This is available at static.your-domain.tld"""
return "static.your-domain.tld"

@app.route("/dynamic", subdomain="<username>")
def username_index(username):
"""Dynamic subdomains are also supported
Try going to user1.your-domain.tld/dynamic"""
return username + ".your-domain.tld"

if __name__ == ‘__main__‘:
app.run()

  1        def auth(func):
  2             def inner(*args, **kwargs):
  3                 print(‘before‘)
  4                 result = func(*args, **kwargs)
  5                 print(‘after‘)
  6                 return result
  7
  8         return inner
  9
 10         @app.route(‘/index.html‘,methods=[‘GET‘,‘POST‘],endpoint=‘index‘)
 11         @auth
 12         def index():
 13             return ‘Index‘
 14
 15         或
 16
 17         def index():
 18             return "Index"
 19
 20         self.add_url_rule(rule=‘/index.html‘, endpoint="index", view_func=index, methods=["GET","POST"])
 21         or
 22         app.add_url_rule(rule=‘/index.html‘, endpoint="index", view_func=index, methods=["GET","POST"])
 23         app.view_functions[‘index‘] = index
 24
 25
 26         或
 27         def auth(func):
 28             def inner(*args, **kwargs):
 29                 print(‘before‘)
 30                 result = func(*args, **kwargs)
 31                 print(‘after‘)
 32                 return result
 33
 34         return inner
 35
 36         class IndexView(views.View):
 37             methods = [‘GET‘]
 38             decorators = [auth, ]
 39
 40             def dispatch_request(self):
 41                 print(‘Index‘)
 42                 return ‘Index!‘
 43
 44         app.add_url_rule(‘/index‘, view_func=IndexView.as_view(name=‘index‘))  # name=endpoint
 45
 46
 47
 48         或
 49
 50
 51         class IndexView(views.MethodView):
 52             methods = [‘GET‘]
 53             decorators = [auth, ]
 54
 55             def get(self):
 56                 return ‘Index.GET‘
 57
 58             def post(self):
 59                 return ‘Index.POST‘
 60
 61
 62         app.add_url_rule(‘/index‘, view_func=IndexView.as_view(name=‘index‘))  # name=endpoint
 63
 64
 65
 66
 67         @app.route和app.add_url_rule参数:
 68             rule,                       URL规则
 69             view_func,                  视图函数名称
 70             defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={‘k‘:‘v‘}为函数提供参数
 71             endpoint=None,              名称,用于反向生成URL,即: url_for(‘名称‘)
 72             methods=None,               允许的请求方式,如:["GET","POST"]
 73
 74
 75             strict_slashes=None,        对URL最后的 / 符号是否严格要求,
 76                                         如:
 77                                             @app.route(‘/index‘,strict_slashes=False),
 78                                                 访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
 79                                             @app.route(‘/index‘,strict_slashes=True)
 80                                                 仅访问 http://www.xx.com/index
 81             redirect_to=None,           重定向到指定地址
 82                                         如:
 83                                             @app.route(‘/index/<int:nid>‘, redirect_to=‘/home/<nid>‘)
 84                                             或
 85                                             def func(adapter, nid):
 86                                                 return "/home/888"
 87                                             @app.route(‘/index/<int:nid>‘, redirect_to=func)
 88             subdomain=None,             子域名访问
 89                                                 from flask import Flask, views, url_for
 90
 91                                                 app = Flask(import_name=__name__)
 92                                                 app.config[‘SERVER_NAME‘] = ‘wupeiqi.com:5000‘
 93
 94
 95                                                 @app.route("/", subdomain="admin")
 96                                                 def static_index():
 97                                                     """Flask supports static subdomains
 98                                                     This is available at static.your-domain.tld"""
 99                                                     return "static.your-domain.tld"
100
101
102                                                 @app.route("/dynamic", subdomain="<username>")
103                                                 def username_index(username):
104                                                     """Dynamic subdomains are also supported
105                                                     Try going to user1.your-domain.tld/dynamic"""
106                                                     return username + ".your-domain.tld"
107
108
109                                                 if __name__ == ‘__main__‘:
110                                                     app.run()
111         

3、自定义路由匹配(正则匹配)

from flask import Flask, views, url_for
from werkzeug.routing import BaseConverter

app = Flask(import_name=__name__)

class RegexConverter(BaseConverter):
"""
自定义URL匹配正则表达式
"""
def __init__(self, map, regex):
super(RegexConverter, self).__init__(map)
self.regex = regex

def to_python(self, value):
"""
路由匹配时,匹配成功后传递给视图函数中参数的值
:param value:
:return:
"""
return int(value)

def to_url(self, value):
"""
使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
:param value:
:return:
"""
val = super(RegexConverter, self).to_url(value)
return val

# 添加到flask中
app.url_map.converters[‘regex‘] = RegexConverter

@app.route(‘/index/<regex("\d+"):nid>‘)
def index(nid):
print(url_for(‘index‘, nid=‘888‘))
return ‘Index‘

if __name__ == ‘__main__‘:
app.run()

 1            from flask import Flask, views, url_for
 2             from werkzeug.routing import BaseConverter
 3
 4             app = Flask(import_name=__name__)
 5
 6
 7             class RegexConverter(BaseConverter):
 8                 """
 9                 自定义URL匹配正则表达式
10                 """
11                 def __init__(self, map, regex):
12                     super(RegexConverter, self).__init__(map)
13                     self.regex = regex
14
15                 def to_python(self, value):
16                     """
17                     路由匹配时,匹配成功后传递给视图函数中参数的值
18                     :param value:
19                     :return:
20                     """
21                     return int(value)
22
23                 def to_url(self, value):
24                     """
25                     使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
26                     :param value:
27                     :return:
28                     """
29                     val = super(RegexConverter, self).to_url(value)
30                     return val
31
32             # 添加到flask中
33             app.url_map.converters[‘regex‘] = RegexConverter
34
35
36             @app.route(‘/index/<regex("\d+"):nid>‘)
37             def index(nid):
38                 print(url_for(‘index‘, nid=‘888‘))
39                 return ‘Index‘
40
41
42             if __name__ == ‘__main__‘:
43                 app.run()

四、Flask模版

1、模板的使用

Flask使用的是Jinja2模板,所以其语法和Django无差别

2、自定义模板方法

Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>自定义函数</h1>
{{ww()|safe}}

</body>
</html>
复制代码

html

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title></title>
 6 </head>
 7 <body>
 8     <h1>自定义函数</h1>
 9     {{ww()|safe}}
10
11 </body>
12 </html>
13 复制代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask,render_template
app = Flask(__name__)

def wangshuyang():
return ‘<h1>Wupeiqi</h1>‘

@app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])
def login():
return render_template(‘login.html‘, ww=wangshuyang)

app.run()

五、Flask请求与响应

from flask import Flask
from flask import request
from flask import render_template
from flask import redirect
from flask import make_response

app = Flask(__name__)

@app.route(‘/login.html‘, methods=[‘GET‘, "POST"])
def login():

# 请求相关信息
# request.method
# request.args
# request.form
# request.values
# request.cookies
# request.headers
# request.path
# request.full_path
# request.script_root
# request.url
# request.base_url
# request.url_root
# request.host_url
# request.host
# request.files
# obj = request.files[‘the_file_name‘]
# obj.save(‘/var/www/uploads/‘ + secure_filename(f.filename))

# 响应相关信息
# return "字符串"
# return render_template(‘html模板路径‘,**{})
# return redirect(‘/index.html‘)

# response = make_response(render_template(‘index.html‘))
# response是flask.wrappers.Response类型
# response.delete_cookie(‘key‘)
# response.set_cookie(‘key‘, ‘value‘)
# response.headers[‘X-Something‘] = ‘A value‘
# return response

return "内容"

if __name__ == ‘__main__‘:
app.run()

 1    from flask import Flask
 2     from flask import request
 3     from flask import render_template
 4     from flask import redirect
 5     from flask import make_response
 6
 7     app = Flask(__name__)
 8
 9
10     @app.route(‘/login.html‘, methods=[‘GET‘, "POST"])
11     def login():
12
13         # 请求相关信息
14         # request.method
15         # request.args
16         # request.form
17         # request.values
18         # request.cookies
19         # request.headers
20         # request.path
21         # request.full_path
22         # request.script_root
23         # request.url
24         # request.base_url
25         # request.url_root
26         # request.host_url
27         # request.host
28         # request.files
29         # obj = request.files[‘the_file_name‘]
30         # obj.save(‘/var/www/uploads/‘ + secure_filename(f.filename))
31
32         # 响应相关信息
33         # return "字符串"
34         # return render_template(‘html模板路径‘,**{})
35         # return redirect(‘/index.html‘)
36
37         # response = make_response(render_template(‘index.html‘))
38         # response是flask.wrappers.Response类型
39         # response.delete_cookie(‘key‘)
40         # response.set_cookie(‘key‘, ‘value‘)
41         # response.headers[‘X-Something‘] = ‘A value‘
42         # return response
43
44
45         return "内容"
46
47     if __name__ == ‘__main__‘:
48         app.run()

六、Flask之Session

除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。

  • 设置:session[‘username‘] = ‘xxx‘
  • 删除:session.pop(‘username‘, None)

1、基本使用

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

@app.route(‘/‘)
def index():
if ‘username‘ in session:
return ‘Logged in as %s‘ % escape(session[‘username‘])
return ‘You are not logged in‘

@app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])
def login():
if request.method == ‘POST‘:
session[‘username‘] = request.form[‘username‘]
return redirect(url_for(‘index‘))
return ‘‘‘
<form action="" method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
‘‘‘

@app.route(‘/logout‘)
def logout():
# remove the username from the session if it‘s there
session.pop(‘username‘, None)
return redirect(url_for(‘index‘))

# set the secret key. keep this really secret:
app.secret_key = ‘A0Zr98j/3yX R~XHH!jmN]LWX/,?RT‘

 1 from flask import Flask, session, redirect, url_for, escape, request
 2
 3 app = Flask(__name__)
 4
 5 @app.route(‘/‘)
 6 def index():
 7     if ‘username‘ in session:
 8         return ‘Logged in as %s‘ % escape(session[‘username‘])
 9     return ‘You are not logged in‘
10
11 @app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])
12 def login():
13     if request.method == ‘POST‘:
14         session[‘username‘] = request.form[‘username‘]
15         return redirect(url_for(‘index‘))
16     return ‘‘‘
17         <form action="" method="post">
18             <p><input type=text name=username>
19             <p><input type=submit value=Login>
20         </form>
21     ‘‘‘
22
23 @app.route(‘/logout‘)
24 def logout():
25     # remove the username from the session if it‘s there
26     session.pop(‘username‘, None)
27     return redirect(url_for(‘index‘))
28
29 # set the secret key.  keep this really secret:
30 app.secret_key = ‘A0Zr98j/3yX R~XHH!jmN]LWX/,?RT‘

2、自定义session(Flask-Session插件)

pip3 install Flask-Session

run.py
from flask import Flask
from flask import session
from pro_flask.utils.session import MySessionInterface
app = Flask(__name__)

app.secret_key = ‘A0Zr98j/3yX R~XHH!jmN]LWX/,?RT‘
app.session_interface = MySessionInterface()

@app.route(‘/login.html‘, methods=[‘GET‘, "POST"])
def login():
print(session)
session[‘user1‘] = ‘alex‘
session[‘user2‘] = ‘alex‘
del session[‘user2‘]

return "内容"

if __name__ == ‘__main__‘:
app.run()

session.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import uuid
import json
from flask.sessions import SessionInterface
from flask.sessions import SessionMixin
from itsdangerous import Signer, BadSignature, want_bytes

class MySession(dict, SessionMixin):
def __init__(self, initial=None, sid=None):
self.sid = sid
self.initial = initial
super(MySession, self).__init__(initial or ())

def __setitem__(self, key, value):
super(MySession, self).__setitem__(key, value)

def __getitem__(self, item):
return super(MySession, self).__getitem__(item)

def __delitem__(self, key):
super(MySession, self).__delitem__(key)

class MySessionInterface(SessionInterface):
session_class = MySession
container = {}

def __init__(self):
import redis
self.redis = redis.Redis()

def _generate_sid(self):
return str(uuid.uuid4())

def _get_signer(self, app):
if not app.secret_key:
return None
return Signer(app.secret_key, salt=‘flask-session‘,
key_derivation=‘hmac‘)

def open_session(self, app, request):
"""
程序刚启动时执行,需要返回一个session对象
"""
sid = request.cookies.get(app.session_cookie_name)
if not sid:
sid = self._generate_sid()
return self.session_class(sid=sid)

signer = self._get_signer(app)
try:
sid_as_bytes = signer.unsign(sid)
sid = sid_as_bytes.decode()
except BadSignature:
sid = self._generate_sid()
return self.session_class(sid=sid)

# session保存在redis中
# val = self.redis.get(sid)
# session保存在内存中
val = self.container.get(sid)

if val is not None:
try:
data = json.loads(val)
return self.session_class(data, sid=sid)
except:
return self.session_class(sid=sid)
return self.session_class(sid=sid)

def save_session(self, app, session, response):
"""
程序结束前执行,可以保存session中所有的值
如:
保存到resit
写入到用户cookie
"""
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app)
expires = self.get_expiration_time(app, session)

val = json.dumps(dict(session))

# session保存在redis中
# self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
# session保存在内存中
self.container.setdefault(session.sid, val)

session_id = self._get_signer(app).sign(want_bytes(session.sid))

response.set_cookie(app.session_cookie_name, session_id,
expires=expires, httponly=httponly,
domain=domain, path=path, secure=secure)

  1         pip3 install Flask-Session
  2
  3         run.py
  4             from flask import Flask
  5             from flask import session
  6             from pro_flask.utils.session import MySessionInterface
  7             app = Flask(__name__)
  8
  9             app.secret_key = ‘A0Zr98j/3yX R~XHH!jmN]LWX/,?RT‘
 10             app.session_interface = MySessionInterface()
 11
 12             @app.route(‘/login.html‘, methods=[‘GET‘, "POST"])
 13             def login():
 14                 print(session)
 15                 session[‘user1‘] = ‘alex‘
 16                 session[‘user2‘] = ‘alex‘
 17                 del session[‘user2‘]
 18
 19                 return "内容"
 20
 21             if __name__ == ‘__main__‘:
 22                 app.run()
 23
 24         session.py
 25             #!/usr/bin/env python
 26             # -*- coding:utf-8 -*-
 27             import uuid
 28             import json
 29             from flask.sessions import SessionInterface
 30             from flask.sessions import SessionMixin
 31             from itsdangerous import Signer, BadSignature, want_bytes
 32
 33
 34             class MySession(dict, SessionMixin):
 35                 def __init__(self, initial=None, sid=None):
 36                     self.sid = sid
 37                     self.initial = initial
 38                     super(MySession, self).__init__(initial or ())
 39
 40
 41                 def __setitem__(self, key, value):
 42                     super(MySession, self).__setitem__(key, value)
 43
 44                 def __getitem__(self, item):
 45                     return super(MySession, self).__getitem__(item)
 46
 47                 def __delitem__(self, key):
 48                     super(MySession, self).__delitem__(key)
 49
 50
 51
 52             class MySessionInterface(SessionInterface):
 53                 session_class = MySession
 54                 container = {}
 55
 56                 def __init__(self):
 57                     import redis
 58                     self.redis = redis.Redis()
 59
 60                 def _generate_sid(self):
 61                     return str(uuid.uuid4())
 62
 63                 def _get_signer(self, app):
 64                     if not app.secret_key:
 65                         return None
 66                     return Signer(app.secret_key, salt=‘flask-session‘,
 67                                   key_derivation=‘hmac‘)
 68
 69                 def open_session(self, app, request):
 70                     """
 71                     程序刚启动时执行,需要返回一个session对象
 72                     """
 73                     sid = request.cookies.get(app.session_cookie_name)
 74                     if not sid:
 75                         sid = self._generate_sid()
 76                         return self.session_class(sid=sid)
 77
 78                     signer = self._get_signer(app)
 79                     try:
 80                         sid_as_bytes = signer.unsign(sid)
 81                         sid = sid_as_bytes.decode()
 82                     except BadSignature:
 83                         sid = self._generate_sid()
 84                         return self.session_class(sid=sid)
 85
 86                     # session保存在redis中
 87                     # val = self.redis.get(sid)
 88                     # session保存在内存中
 89                     val = self.container.get(sid)
 90
 91                     if val is not None:
 92                         try:
 93                             data = json.loads(val)
 94                             return self.session_class(data, sid=sid)
 95                         except:
 96                             return self.session_class(sid=sid)
 97                     return self.session_class(sid=sid)
 98
 99                 def save_session(self, app, session, response):
100                     """
101                     程序结束前执行,可以保存session中所有的值
102                     如:
103                         保存到resit
104                         写入到用户cookie
105                     """
106                     domain = self.get_cookie_domain(app)
107                     path = self.get_cookie_path(app)
108                     httponly = self.get_cookie_httponly(app)
109                     secure = self.get_cookie_secure(app)
110                     expires = self.get_expiration_time(app, session)
111
112                     val = json.dumps(dict(session))
113
114                     # session保存在redis中
115                     # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
116                     # session保存在内存中
117                     self.container.setdefault(session.sid, val)
118
119                     session_id = self._get_signer(app).sign(want_bytes(session.sid))
120
121                     response.set_cookie(app.session_cookie_name, session_id,
122                                         expires=expires, httponly=httponly,
123                                         domain=domain, path=path, secure=secure)

七、Flask之蓝图

蓝图用于为应用提供目录划分:

小型应用程序:示例

大型应用程序:示例

其他:

  • 蓝图URL前缀:xxx = Blueprint(‘account‘, __name__,url_prefix=‘/xxx‘)
  • 蓝图子域名:xxx = Blueprint(‘account‘, __name__,subdomain=‘admin‘)
    # 前提需要给配置SERVER_NAME: app.config[‘SERVER_NAME‘] = ‘wupeiqi.com:5000‘
    # 访问时:admin.wupeiqi.com:5000/login.html

八、Flask之message

message是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。(也称为闪现)

from flask import Flask, flash, redirect, render_template, request, get_flashed_messages

app = Flask(__name__)
app.secret_key = ‘some_secret‘

@app.route(‘/‘)
def index1():
messages = get_flashed_messages()
print(messages)
return "Index1"

@app.route(‘/set‘)
def index2():
v = request.args.get(‘p‘)
flash(v)
return ‘ok‘

if __name__ == "__main__":
app.run()

 1         from flask import Flask, flash, redirect, render_template, request, get_flashed_messages
 2
 3         app = Flask(__name__)
 4         app.secret_key = ‘some_secret‘
 5
 6
 7         @app.route(‘/‘)
 8         def index1():
 9             messages = get_flashed_messages()
10             print(messages)
11             return "Index1"
12
13
14         @app.route(‘/set‘)
15         def index2():
16             v = request.args.get(‘p‘)
17             flash(v)
18             return ‘ok‘
19
20
21         if __name__ == "__main__":
22             app.run()

九、中间件

from flask import Flask, flash, redirect, render_template, request

app = Flask(__name__)
app.secret_key = ‘some_secret‘

@app.route(‘/‘)
def index1():
return render_template(‘index.html‘)

@app.route(‘/set‘)
def index2():
v = request.args.get(‘p‘)
flash(v)
return ‘ok‘

class MiddleWare:
def __init__(self, wsgi_app):
self.wsgi_app = wsgi_app

def __call__(self, *args, **kwargs):
# 执行前操作
res = self.wsgi_app(*args, **kwargs)
# 执行后操作
return res

if __name__ == "__main__":
app.wsgi_app = MiddleWare(app.wsgi_app)
app.run(port=9999)

 1 from flask import Flask, flash, redirect, render_template, request
 2
 3 app = Flask(__name__)
 4 app.secret_key = ‘some_secret‘
 5
 6 @app.route(‘/‘)
 7 def index1():
 8     return render_template(‘index.html‘)
 9
10 @app.route(‘/set‘)
11 def index2():
12     v = request.args.get(‘p‘)
13     flash(v)
14     return ‘ok‘
15
16 class MiddleWare:
17     def __init__(self, wsgi_app):
18         self.wsgi_app = wsgi_app
19
20     def __call__(self, *args, **kwargs):
21         # 执行前操作
22         res = self.wsgi_app(*args, **kwargs)
23         # 执行后操作
24         return res
25
26 if __name__ == "__main__":
27     app.wsgi_app = MiddleWare(app.wsgi_app)
28     app.run(port=9999) 

十、Flask插件

  • Flask-Session
  • WTForms
  • SQLAchemy
  • 等...

原文地址:https://www.cnblogs.com/dingjiaoyang/p/10986422.html

时间: 2024-08-30 04:42:12

python高级之Flask框架的相关文章

Python语言和Flask框架

百科Python  : Python,是一种面向对象.直译式计算机程序设计语言:Python语法简捷而清晰,具有丰富和强大的类库.它常被昵称为胶水语言,它能够很轻松的把用其他语言制作的各种模块(尤其是C/C++)轻松地联结在一起.常见的一种应用情形是,使用python快速生成程序的原型(有时甚至是程序的最终界面),然后对其中有特别要求的部分,用更合适的语言改写,比如3D游戏中的图形渲染模块,速度要求非常高,就可以用C++重写. 基于C的Python编译出的字节码文件,通常是.pyc格式. Fla

Python轻量Web框架Flask使用

http://blog.csdn.net/jacman/article/details/49098819 目录(?)[+] Flask安装 Python开发工具EclipsePyDev准备 Flask项目框架搭建 MVC模式实例开发 登录实例 Python语言近些年越来越火,其特点是开发迅速,语法简单,可移植等.本人就Python3基础语法写了Demo:https://github.com/tangthis/python3_demo,可以当作基础教程和手册查阅. Python Web开发框架常用

基于Flask框架的Python web程序的开发实战 &lt;一&gt; 环境搭建

最近在看<Flask Web开发基于Python的Web应用开发实战>Miguel Grinberg著.安道译 这本书,一步步跟着学习Flask框架的应用,这里做一下笔记 电脑只安装一个Python2.7就行了,用的IDE还是官方那个跟记事本差不多的编辑器,先原始一点,以后再用PyCharm开发,我系统是Win8.1 x64 一:虚拟环境配置 虚拟环境使用第三方工具virtualenv创建,打开cmd,输入virtualenv命令来检测是否已经安装,我已经装过了,所以会提示:You must

真正搞明白Python中Django和Flask框架的区别

在谈Python中Django框架和Flask框架的区别之前,我们需要先探讨如下几个问题. 一.为什么要使用框架? 为了更好地阐述这个问题,我们把开发一个应用的过程进行类比,往往开发一个应用(web应用.系统应用)跟建造房子的过程一样,需要先打地基,搭好骨架,然后一块砖一块砖叠上去. 而开发一个应用呢?同样也需要一个好的架构设计,数据库建模,然后一个模块一个模块使用代码实现. 如果开发一个软件应用不使用框架,和我们建房子时,每一块砖.每一根钢筋都需要自己生产出来本质上是一样的. 显而易见,如果在

一线Python运维澳洲5盘口出租搭建开发带你秒懂Flask框架

大家好,下面现在开始分享flask开发,先看下本次分享的内容: 1.Flask Web框架介绍 Flask是微型web框架,框架本身十分精简,微型并不代表其功能弱,核心代码基于Werkzeug, Jinja 2 这两个库,它以插件形式的进行功能扩展,且插件易于安装与使用,并且可以自行开发扩展插件 与其他web框架类似,flask中请求(request),路由(route),响应(response)构成其完整的一个基本http流程. 2.作为入门flask框架非常易于使用 了解其基本结构后,可以迅

python flask框架学习(一)——准备工作和环境配置与安装

Flask装备: 学习自:知了课堂Python Flask框架——全栈开发 1.Python版本:3.6 2.Pycharm软件: 3.安装虚拟环境: (1)安装virtualenv: pip install virtualenv (2)安装virtualenvwrapper: windows: pip install virtualenvwrapper-win 4.virtualenvwrapper的使用 (1)创建虚拟环境 mkvirtualenv flask-env (2)切换到某个虚拟环

python flask框架学习——开启debug模式

学习自:知了课堂Python Flask框架——全栈开发 1.flask的几种debug模式的方法 # 1.app.run 传参debug=true app.run(debug=True) #2 设置app的配置 app = Flask(__name__) app.config['DEBUG'] = True #3 配置文件方式 # config.py中添加debug模式 DEBUG = True #app.py中引用配置 import config app.config.from_object

002:python用flask框架开发第一个demo接口

从2020年开始,学习记录开始加入编号了~ 002:python用flask框架开发第一个demo接口 1.安装flask库,cmd命令进入到python37安装目录的scripts中pip3 install flask: 2.开始写代码 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import flask 4 import json 5 6 """flask 开发第一个demo接口"""

宝塔面板部署Python的Flask框架项目

以Linux版宝塔面板为例.本篇文章给大家介绍宝塔面板如何部署Flask项目. 先做好准备工作: 进入你的项目根目录,使用命令把项目依赖包导出到项目根目录. pip freeze >requirements.txt 然后把你的项目上传到服务器. 把你的Flask框架项目中的 第一步: 在宝塔应用商店点击“宝塔插件”或搜索“python”找到“Python项目管理器”并安装. 第二步:安装完毕后点击“设置”按钮. 第三步:进行设置界面,单击“版本管理”,安装你项目需要的python版本: 第四步: