目录
反向解析, 配置信息, 路由系统, 模板, 请求响应, 闪现, session
一, 反向解析
1, 什么是反向解析
2, 使用
二, 配置信息
1, 默认配置
2, 修改方法一 -- 点的方式修改
3, 修改方法二 -- 利用字典修改
4, 修改方法三 -- 通过 py 文件修改(常用)
5, 修改方法四 -- 利用类或类的路径修改(常用)
6, 其他方法修改配置
三, 路由系统
1, 基本写法
2, 转换器
3, 路由本质
4,CBV
5, 自定义支持正则
四, 模板
五, 请求与响应
六, session
七, 闪现(flash)
1, 使用
2, 示例
反向解析, 配置信息, 路由系统, 模板, 请求响应, 闪现, session
一, 反向解析
1, 什么是反向解析
随着功能的增加会出现更多的视图, 路由可能会发生改变, 那么能让链接根据正则表达式动态生成吗? 就是用反向解析的办法.
2, 使用
flask 中使用 url_for 来反向解析
- # url_for 根据别名来反向解析获取路由
- url = url_for(endpoint 指定的别名)
- from flask import Flask, views, url_for
- App = Flask(import_name=__name__)
- @App.route('/', endpoint='index')
- def index():
- return 'index'
- @App.route('/test')
- def func():
- url = url_for('index') # url_for 根据别名来反向解析获取路由
- print(url)
- return redirect(url)
- 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,
- }
2, 修改方法一 -- 点的方式修改
利用点来修改, 该方法能修改的配置信息数量有限
- App.debug = True
- App.secret_key = 'asdfgh'
3, 修改方法二 -- 利用字典修改
- App.config['DEBUG'] = True
- # 由于配置文件继承自字典, 所以可以用修改字典的方式修改
- # 由于 Config 对象本质上是字典, 所以还可以使用 App.config.update(...)
4, 修改方法三 -- 通过 py 文件修改(常用)
从 sys.path 中已经存在路径开始写
settings.py 文件默认路径要放在程序 root_path 目录. 如果没有放在根目录下, instance_relative_config 为 True, 则目录就是 instance_path 目录(Flask 对象 init 方法的参数)
- instance_relative_config = True
- instance_path = '配置文件 settings.py 的目录'
- # 利用 from_pyfile 来修改配置
- App.config.from_pyfile(文件名)
1. 创建一个配置文件 settings.py
2. 在 settings.py 中写配置
3. 利用 App.from_pyfile('settings.py'), 来讲默认配置文件中的配置替换掉
- # settings.py
- SECRET_KEY = '123asdf'
- # main.py
- from flask import Flask, session
- App = Flask(__name__)
- App.config.from_pyfile('settings.py') # 利用 from_pyfile 来修改配置
- @App.route('/')
- def func():
- session['user'] = 'tom'
- return session.get('user')
- if __name__ == '__main__':
- App.run()
5, 修改方法四 -- 利用类或类的路径修改(常用)
从 sys.path 中已经存在路径开始写
settings.py 文件默认路径要放在程序 root_path 目录. 如果没有放在根目录下, instance_relative_config 为 True, 则目录就是 instance_path 目录(Flask 对象 init 方法的参数)
- instance_relative_config = True
- instance_path = '配置文件 settings.py 的目录'
- App.config.from_mapping({'DEBUG': True}) # 字典格式
- App.config.from_object("python 类或类的路径")
- # 利用类或类的路径, 如下:
- # main.py
- 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://user@localhost/foo'
- class DevelopmentConfig(Config):
- DEBUG = True
- class TestingConfig(Config):
- TESTING = True
6, 其他方法修改配置
- # 1. 通过环境变量配置 from_envvar
- App.config.from_envvar("环境变量名称")
- App.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])
环境变量的值为 python 文件名称名称, 内部调用 from_pyfile 方法
- # 2.from_json
- App.config.from_json("json 文件名称")
JSON 文件名称, 必须是 JSON 格式, 因为内部会执行 JSON.loads
三, 路由系统
1, 基本写法
- @App.route('/index',methods=['GET','POST'],endpoint='index')
- @App.route('/detail/<int:nid>',methods=['GET'],endpoint='detail') # 使用转换器
2, 转换器
- DEFAULT_CONVERTERS = {
- 'default': UnicodeConverter,
- 'string': UnicodeConverter,
- 'any': AnyConverter,
- 'path': PathConverter,
- 'int': IntegerConverter,
- 'float': FloatConverter,
- 'uuid': UUIDConverter,
- }
3, 路由本质
- @App.route('/index')
- def test():
- return 'ok'
- # 路由本质
- # 1. decorator = App.route('/index')
- def route(self, rule, **options):
- def decorator(f):
- endpoint = options.pop('endpoint', None)
- self.add_url_rule(rule, endpoint, f, **options)
- return f
- return decorator
- # 2. @decorator
- decorator(index)
- # @App.route('/index') 也可以用 add_url_rule(rule, endpoint, f, **options)代替
- App.add_url_rule('/index','index',test,defaults={'id':1})
- def test(id):
- return 'ok'
- # 与 django 路由类似
- # django 与 flask 路由: flask 路由基于装饰器, 本质是基于: add_url_rule
- # add_url_rule 源码中, endpoint 如果为空, endpoint = _endpoint_from_view_func(view_func), 最终取 view_func.__name__(函数名), 默认用函数名字, 所以, 一旦方法名字相同, 路由的别名就会相同
所以用自定义装饰器时, 在没有指定 endpoint, 就会报错. 必须指定 endpoint 不同
4,CBV
(1)基本使用
- def auth(func):
- def inner(*args, **kwargs):
- print('before')
- result = func(*args, **kwargs)
- print('after')
- return result
- return inner
- # 通常用此方式
- class IndexView(views.MethodView):
- methods = ['GET','POST'] # 标明能通过哪些 request 的请求方式
- 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
(2)add_url_rule 参数
@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"]
- # 对 URL 最后的 / 符号是否严格要求, 自动在末尾加上 /
- strict_slashes = None
- ''' @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>')
- '''
- # 子域名访问
- subdomain = None,
- '''
- # C:\Windows\System32\drivers\etc\hosts
- 127.0.0.1 www.liuqingzheng.com
- 127.0.0.1 admin.liuqingzheng.com
- 127.0.0.1 buy.liuqingzheng.com
- from flask import Flask, views, url_for
- app = Flask(import_name=__name__)
- app.config['SERVER_NAME'] = 'liuqingzheng.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"
- # 可以传入任意的字符串, 如传入的字符串为 aa, 显示为 aa.liuqingzheng.com
- @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()
- 访问:
- http://www.liuqingzheng.com:5000/dynamic
- http://admin.liuqingzheng.com:5000/dynamic
- http://buy.liuqingzheng.com:5000/dynamic
- '''
5, 自定义支持正则
- # 1. 写类, 继承 BaseConverter
- # 2. 注册: App.url_map.converters['regex'] = RegexConverter
- # 3. 使用:@App.route('/index/<regex("\d+"):nid>') 正则表达式会当作第二个参数传递到类中
- 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):
- """
- 路由匹配时, 匹配成功后传递给视图函数中参数的值
- """
- return int(value)
- def to_url(self, value):
- """
- 使用 url_for 反向生成 URL 时, 传递的参数经过该方法处理, 返回的值用于生成 URL 中的参数
- """
- 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()
四, 模板
flask 中模板中的函数可以加括号, 执行函数, 传参数
Markup 等价 django 的 make_safe(在视图中使用), 或者利用 safe 实现(在模板层). 默认 flask 会处理掉 xss 攻击
extends , block ,include 等的使用都和 Django 中相同
- from flask import Flask,render_template,Markup
- App = Flask(__name__)
- def func1(arg):
- return Markup("<input type='text'value='%s'/>" %(arg,))
- def func2(arg):
- return Markup("<input type='text'value='%s'/>" %(arg,))
- @App.route('/')
- def index():
- return render_template('index.html',func=func2)
- if __name__ == '__main__':
- App.run()
模板层 index.HTML
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Title
- </title>
- </head>
- <body>
- {{func('六五')}} {{func('六五')|safe}}
- </body>
- </HTML>
五, 请求与响应
- 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():
- # 1. 请求相关信息
- # request.method # 获取请求的方式
- # request.args # 获取 get 请求的数据
- # request.form # 获取 post 请求的数据
- # 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))
- # 2. 响应相关信息
- # return "字符串" # 相当于 Django 中的 HttpResponse
- # return render_template('html 模板路径',**{}) # 相当于 Django 中的 render
- # return redirect('/index.html') # 相当于 Django 中的 redirect
- #return jsonify({'k1':'v1'}) # 相当于 Django 中的 JsonResponse
- # 往响应头里添加数据, 或者写 cookie, 用 make_response
- # response = make_response(render_template('index.html'))
- # response 是 flask.wrappers.Response 类型
- # response.delete_cookie('key') # 删 cookie
- # response.set_cookie('key', 'value') # 设置 cookie
- # response.headers['X-Something'] = 'A value' # 往响应头中写内容
- # return response
- return "内容"
- if __name__ == '__main__':
- App.run()
六, session
除请求对象之外, 还有一个 session 对象. 它允许你在不同请求间存储特定用户的信息. 它是在 Cookies 的基础上实现的, 并且对 Cookies 进行密钥签名要使用会话, 你需要设置一个密钥. (App.session_interface 对象)
session 是继承了字典, 所有操作都可以参照字典来处理
使用 session 一定设置一个密钥
- App.secret_key='asdfasdf'
- from flask import session
- App.secret_key = 'asdghk'
- # 1. 设置 session
- session['user'] = 'tom'
- # 2. 获取 session
- user = session['user']
- # 3. 删除 session
- session.pop['user']
- del session['user']
七, 闪现(flash)
闪现是将消息保存在 flask 中, 等到需要的时候可以从 flask 中获取消息, 并在下一个 (且仅在下一个) 请求中访问记录的信息. 展现这些消息通常结合要模板布局.
假设在 a 页面操作出错, 跳转到 b 页面, 在 b 页面显示 a 页面的错误信息, 就可以先将报错信息保存在 flash 中, 到 b 页面时取出来
1, 使用
- # 1. 设置
- # 第一个参数表示要保存的内容, 第二个参数是 flash 的分类
- flash('ttt',category='t1')
- # 2. 取值
- get_flashed_message()
- get_flashed_messages(category_filter=['x1']) # 获取分类为 x1 的 flash
2, 示例
- from flask import Flask,flash,get_flashed_messages,request,redirect
- App = Flask(__name__)
- App.secret_key = 'asdfasdf'
- @App.route('/index')
- def index():
- # 从某个地方获取设置过的所有值, 并清除.
- val = request.args.get('v')
- if val == 'hello':
- return 'Hello World!'
- flash('超时错误',category="x1")
- return "ssdsdsdfsd"
- # return redirect('/error')
- @App.route('/error')
- def error():
- data = get_flashed_messages(category_filter=['x1']) # 获取分类为 x1 的 flash
- if data:
- msg = data[0]
- else:
- msg = "..."
- return "错误信息:%s" %(msg,)
- if __name__ == '__main__':
- App.run()
来源: https://www.cnblogs.com/ZKPython/p/11390604.html