Flask框架(二)—— 反向解析配置信息路由系统模板请求响应闪现session 目录 反向解析、配置信息、路由系统、模板、请求响应、闪现、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() 博客内容仅供参考,部分参考他人优秀博文,仅供学习使用  
转载自://www.cnblogs.com/ZKPython/p/11390604.html