原文地址:http://www.cnblogs.com/wupeiqi/articles/5341480.html
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架.
Werkzeug本质就是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果返回给用户的内容很复杂,就需要借助jinja2模板引擎来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串数据返回给用户浏览器。
“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。
默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已经准备好在需求繁杂的生产环境中投入使用。
另外的介绍:
Flask诞生于2010年,是Armin ronacher(人名)用 Python 语言基于 Werkzeug 工具箱编写的轻量级Web开发框架。
Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现。比如可以用 Flask 扩展加入ORM、窗体验证工具,文件上传、身份验证等。Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL。
其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是 Flask 框架的核心。
Flask常用扩展包:
- Flask-SQLalchemy:操作数据库;
- Flask-script:插入脚本;
- Flask-migrate:管理迁移数据库;
- Flask-Session:Session存储方式指定;
- Flask-WTF:表单;
- Flask-Mail:邮件;
- Flask-Bable:提供国际化和本地化支持,翻译;
- Flask-Login:认证用户状态;
- Flask-OpenID:认证;
- Flask-RESTful:开发REST API的工具;
- Flask-Bootstrap:集成前端Twitter Bootstrap框架;
- Flask-Moment:本地化日期和时间;
- Flask-Admin:简单而可扩展的管理接口的框架
安装:pip install flask
简单示例:
1 from flask import Flask 2 3 # 创建一个flask的应用程序,名字叫app 4 # flask对象的名字 = Flask(__name__) 5 # app可以随意起名字 6 # __name__:表示模块名 7 8 app = Flask(__name__) 9 10 """ 11 通过装饰器,设置请求的路由 12 路由:就是一个url的地址,或者在java中也叫做接口 13 语法:@flask对象的名字.route("路径") 14 注意:app是对象的名字,名字可以随意取 15 @app.route('/aaa'):参数必须以/开头,否则会报错 ValueError: urls must start with a leading slash 16 def index():def表示定义一个函数,index是函数名字 函数名字随意取 17 """ 18 @app.route('/') 19 def index(): 20 """写我们的业务逻辑""" 21 # return表示展示页面,渲染页面,渲染就是展示的意思 22 return "我是第一个flask应用程序" 23 24 25 # 判断是否是入口 26 # 表示入口函数,固定语法 27 if __name__ == '__main__': 28 # 启动应用程序 29 app.run()
初始化参数介绍:
1 from flask import Flask 2 3 """ 4 查看参数的快捷键:ctrl + p 5 static_path='xxx':静态路径,为了向下兼容,有些低版本使用的是这个 6 static_url_path='xxx':url路径.表示的也是静态路径, 7 表示的是一个意思,目的是为了向下兼容,表示静态文件 8 static_folder='static',表示静态文件夹,系统默认叫static,里面存放静态文件,比如图片等等 9 template_folder='teplates':模板文件夹,里面存放HTML文件 10 """ 11 app = Flask(__name__, static_path=None, static_url_path=None, static_folder='static',template_folder='templates') 12 13 14 @app.route("/") # 千万注意:是/ 不是.是斜杠/ 15 def index(): 16 return "index page" 17 18 19 if __name__ == '__main__': 20 app.run() 21 """ 22 lsof -i 5000:监听5000端口 23 kill -9 4728: 杀死5000端口的应用PID 24 25 PID是进程id 26 27 加载方式: 28 from_object 对象 29 from_pyfile 文件 30 from_envvar 环境变量 31 """
对象方式加载配置文件:
1 """ 2 起名字不要用中文 3 """ 4 from flask import Flask 5 6 app = Flask(__name__) 7 8 9 class Config(object): 10 """创建一个配置类,名字叫Config,名字随便取""" 11 # 开启调试模式,调试模式为True 12 # 自下而上找错误 13 # 加载配置文件的好处:可以看到具体的错误信息,自动定位到错误的位置 14 DEBUG = True 15 # 自定义参数,参数不可以小写.只能是大写 16 # 大小写切换快捷键:ctrl + shift +u 17 ITCAST = "python" 18 19 20 # flask程序 从对象加载配置文件,配置文件来自Config这个对象 21 app.config.from_object(Config) 22 23 24 @app.route("/") 25 def index(): 26 # a = 1 / 0 27 # 如果是自定义的参数,就需要自己取 28 # 如果从对象中取自定义的值,必须从对象读取,不能从文件读取 29 print(app.config.get('ITCAST')) 30 return 'index page' 31 32 33 if __name__ == '__main__': 34 app.run()
文件方式加载配置文件:
注意:先要在同级目录下创建一个config.cfg文件
1 from flask import Flask 2 3 app = Flask(__name__) 4 5 6 class Config(object): 7 """创建一个配置类,名字叫Config,名字随便取""" 8 # 开启调试模式,调试模式为True 9 # 自下而上找错误 10 # 加载配置文件的好处:可以看到具体的错误信息,自动定位 11 DEBUG = True 12 13 14 # flask程序 从文件加载配置文件 15 # 从对象加载必须 掌握,文件加载也得会 16 # 从对象加载的参数里面传入的是对象 17 # 从文件加载的参数里面传入的是文件名,是字符串类型,有引号 18 app.config.from_pyfile("config.cfg") 19 20 21 @app.route("/") 22 def index(): 23 a = 1 / 0 24 return 'index page' 25 26 27 if __name__ == '__main__': 28 app.run()
run()参数:
1 from flask import Flask 2 3 app = Flask(__name__) 4 5 6 @app.route('/') 7 def index(): 8 a = 1/0 9 return 'index page' 10 11 12 if __name__ == '__main__': 13 """ 14 修改ip地址: 15 第一个参数是ip地址, 16 第二个是端口号, 17 第三个是开启调试模式(和之前的DEBUG是一样的功能, 18 这里是系统为了方便写在这里的.开发的时候需要自己写) 19 20 一般不建议修改,就使用这个默认的值就好 21 """ 22 app.run(host='192.168.14.27', port=9000, debug=True)
开启debug=True模式后,详细的报错信息就会展示在控制台.
路由系统:
- @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'])
常用路由系统有以上五种,所有的路由系统都是基于下面的对应关系来处理:
1 #: the default converter mapping for the map. 2 DEFAULT_CONVERTERS = { 3 'default': UnicodeConverter, 4 'string': UnicodeConverter, 5 'any': AnyConverter, 6 'path': PathConverter, 7 'int': IntegerConverter, 8 'float': FloatConverter, 9 'uuid': UUIDConverter, 10 }
自定义转换器进行正则匹配:
1 """ 2 之前只是限制数据类型,今天限制更多了. 3 限制位数,每一位的数据类型等 4 """ 5 from flask import Flask 6 7 # routing 和路由相关的都在这里 第一步: 8 from werkzeug.routing import BaseConverter 9 """ 10 转换器:converter 11 """ 12 13 app = Flask(__name__) 14 15 16 # 需要自定义转换器,通过正则方式进行自定义转换器, 17 # alt+enter快捷键就是进行导包 第二步:继承 18 class RegBaseConverter(BaseConverter): 19 # 表示限制的数据类型是数字,并且只能是5位,regex不能随便取,只能是regex,父类中定义好了 20 regex = 'd{5}' 21 22 23 # app.url_map得到所有的url地址(也就是路由) 24 # converters 表示转换器 25 # 自定义转换器,那么需要给自定义转换器起一个名字.注意:自己取的名字不能和系统的重名 26 # 把我们自定义的转换器放到converters这个转换器的集合里面 第三步:添加到转换器字典中 27 app.url_map.converters['aaaaaa'] = RegBaseConverter 28 29 30 # 限制数据类型是整型,只能限制数据类型.不能限制参数的位数.不好用. 31 # <aaaaaa:index_id>:进行替换,aaaaaa在这里就代表上面的正则表达式 第四步:使用 32 @app.route('/index/<aaaaaa:index_id>') 33 def index(index_id): 34 return 'index=%s' % index_id 35 36 37 if __name__ == '__main__': 38 app.run() 39 """ 40 DEFAULT_CONVERTERS = { 41 'default': UnicodeConverter, 42 'string': UnicodeConverter, 43 'any': AnyConverter, 44 'path': PathConverter, 45 'int': IntegerConverter, 46 'float': FloatConverter, 47 'uuid': UUIDConverter, 48 } 49 50 一共6种转换器,前面两种是一样的.默认的是接收所有的和字符型一样 51 """
更专业的解答:https://segmentfault.com/q/1010000000125259
模板:
1、模板的使用
Flask使用的是Jinja2模板,所以其语法和Django无差别
2、自定义模板方法
Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>模板</title> 6 </head> 7 <body> 8 <h1>获取到后台传来的数据:</h1> 9 {# {{ 变量名 }} 表示模板文件的语法,用来获取后端传来的变量 #} 10 {# 变量.键 的方式获取键对应的值 只要是字典格式的数据,获取key对应的value 11 都是采用对象/变量 .key的方式 12 #} 13 {#使用p标签之后,输出显示就是一行一行的显示#} 14 <p>名字:{{ data_obj.name }}</p> 15 <p>年龄{{ data_obj.age }}</p> 16 <p>地址:{{ data_obj.address }}</p> 17 <p>列表数据:{{ data_obj.my_list }}</p> 18 <p>字典中的城市数据:{{ data_obj.my_dict.city }}</p> 19 </body> 20 </html>
对应的后台.py文件:
1 from flask import Flask, render_template 2 3 app = Flask(__name__) 4 5 """ 6 模板传递数据: 7 注意: 8 模板其实是一个包含响应文本的文件. 9 本质就是一个响应的文件.记住:是文件,文件 10 误区:模板就是HTML. 11 12 作用: 13 1.降低耦合度,更好的控制代码 14 """ 15 16 17 @app.route('/login') 18 def index(): 19 # 业务逻辑已实现 20 # 处理用户名,密码 21 data = { 22 'name': 'libin', 23 'age': 56, 24 'address': 'USA', 25 'my_list': [1, 2, '45'], 26 'my_dict': {'city': 'sz'} 27 } 28 # 第一个参数是模板文件的名字, 29 # 第二个参数是需要传递到文件上面的数据,前面参数是占位符,后面的是变量的名字 30 return render_template('demo1.html', data_obj=data) 31 32 33 if __name__ == '__main__': 34 app.run()
公共组件:
1、请求
对于Http请求,Flask会讲请求信息封装在request中(werkzeug.wrappers.BaseRequest),提供的如下常用方法和字段以供使用:
1 request.method 2 request.args 3 request.form 4 request.values 5 request.files 6 request.cookies 7 request.headers 8 request.path 9 request.full_path 10 request.script_root 11 request.url 12 request.base_url 13 request.url_root 14 request.host_url 15 request.host
常用的介绍:
args参数:
1 # ------------------------------args参数------------------- 2 """ 3 args:就是get请求时url后面加?的后面的数据 4 """ 5 from flask import Flask, request 6 7 app = Flask(__name__) 8 9 10 @app.route('/index', methods=['GET', 'POST']) 11 def index(): 12 # ?号后面的数据 13 # request.args :获取到?后面的数据 14 city = request.args.get('city') 15 print(city) 16 return 'index' 17 18 19 if __name__ == '__main__': 20 app.run()
form表单数据:
1 """ 2 request获取数据 3 """ 4 # -------------------form表单------------------------- 5 from flask import Flask, request 6 7 app = Flask(__name__) 8 9 10 @app.route('/index', methods=['GET', 'POST']) 11 def index(): 12 print('前端请求的url地址:', request.url) 13 """所有的请求数据都是封装在request里面""" 14 # request.form:获取到表单数据 15 # request.form.get():获取到表单里面具体的某一个数据 16 name = request.form.get('name') 17 pwd = request.form.get('pwd') 18 return 'name=%s,pwd=%s' % (name, pwd) 19 20 21 if __name__ == '__main__': 22 app.run()
files多媒体数据:
1 # -----------------------files多媒体------------------- 2 from flask import Flask, request 3 4 app = Flask(__name__) 5 6 7 # 上传图片,只能选POST方式 8 @app.route('/', methods=['POST']) 9 def index(): 10 # request.files 获取多媒体数据,比如拿到图片 11 pic = request.files.get('pic') 12 # pic.save('./bb.png') :保存图片,上传图片 13 pic.save('./bb.png') 14 return '上传成功!' 15 16 17 if __name__ == '__main__': 18 app.run()
返回JSON格式数据:
from flask import Flask, jsonify app = Flask(__name__) # -------------------就是返回给客户端呈现的数据是json格式的----------- @app.route('/') def index(): data = { "name": "python", "age": 29 } # -------------jsonify方式------------------------------------------- return jsonify(data) if __name__ == '__main__': app.run()
原生方式返回JSON:
# ------------------------原生方式:json.dumps()---------------------------- from flask import Flask import json app = Flask(__name__) @app.route('/') def index(): data = { "name": "python", "age": 29 } # -------------原生方式json.dumps()-------- # 直接返回报错,需要进行包装一下,告诉系统这是个json数据.python默认会识别为字典 # json.dumps()字典数据转成json数据 res = json.dumps(data) # 第一个参数表示内容,第二个参数表示状态码,第三个表示数据类型 return res, 200, {'Content-Type': 'application/json'} if __name__ == '__main__': app.run()
重定向:
1 """ 2 重定向:请求页面的时候,请求页面不存在,返回的是另外一个页面. 3 一般在双11的活动的时候,活动页面... 4 京东原来的域名www.360.buy.com,如果访问原来的就需要跳转到现在的域名www.jd.com 5 6 """ 7 from flask import Flask, redirect, url_for # redirect, url_for 这两个是重定向模块 8 9 app = Flask(__name__) 10 11 12 @app.route('/360buy') 13 def index(): 14 # redirect 重定向 15 """ 16 17 url_for会根据传入的路由函数名,返回该路由对应的URL,在模板中始终使用url_for()就可以安全的修改路由绑定的URL,则不必担心模板中渲染url链接出错: 18 19 """ 20 return redirect(url_for('jd')) 21 22 23 @app.route('/jd') 24 def jd(): 25 return '进入到京东商城页面' 26 27 28 if __name__ == '__main__': 29 app.run()
自定义状态码:
1 from flask import Flask 2 3 app = Flask(__name__) 4 5 """ 6 自定义状态码: 7 使用场景: 8 错误代码的对照表.可以自己定义相关的错误.比如实际开发中的具体错误:10004表示注册成功后未登录等等 9 10 在交互成功之后要求交互成功的内容再具体一点,是交互的哪些内容成功? 11 """ 12 13 14 @app.route('/') 15 def index(): 16 # 999 是请求状态码,是自定义的状态码 17 return 'index', 999 # 返回客户端给用户看的,999表示...错误 18 19 20 if __name__ == '__main__': 21 app.run()
abort异常捕获:
1 """ 2 abort的作用: 3 1.捕获HTTP的异常(之前是try...exception抓取),这里flask重新进行了封装. 4 2.终止程序 5 3.抛出异常 6 7 细节-注意:在abort(500)函数中和@app.errorhandler(500)中, 8 参数必须是http协议标准的状态码. 9 10 abort(状态码)和@app.errorhandler(状态码)中的参数都是状态码,这两个状态码必须一致.即这两个参数必须一致. 11 12 abort(参数1)和@app.errorhandler(参数2):注意,参数1和参数2必须一致 13 14 15 在开发中实际应用: 16 1.一般用来展示404的页面(资源没找到,请求页面不存在) 17 18 19 """ 20 from flask import Flask, abort 21 22 app = Flask(__name__) 23 24 25 @app.route('/') 26 def index(): 27 name = '' 28 pwd = '' 29 30 if name != 'admin' and pwd != '123': 31 print('进入了函数') 32 # 把程序终止掉,后面的业务逻辑就不需要执行了,因为即使执行也没有实际意义 33 abort(500) 34 # 进入到数据库,进行数据库查询 35 print('看看我进入数据库了没') 36 return 'index page' 37 38 39 @app.errorhandler(500) # 抛出捕获到的异常信息 40 def error_500_handler(error): 41 # return '程序报错了:%s' % error 42 return '替换为一个html页面' 43 44 45 if __name__ == '__main__': 46 app.run()
内置过滤器filter:
1 from flask import Flask, render_template 2 3 app = Flask(__name__) 4 5 """ 6 过滤器本质就是一个函数. 7 作用: 8 1.不仅仅只是输出值 9 2.还希望更改值 10 11 """ 12 13 14 @app.route('/') 15 def index(): 16 return render_template('demo2.html') 17 18 19 if __name__ == '__main__': 20 app.run()
对应的HTML:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>过滤器</title> 6 </head> 7 <body> 8 <h1>过滤器的使用</h1> 9 {#{{ 需要修改的值|过滤器的名字 }}#} 10 {# capitalize: 首字母大写#} 11 <p>首字母大写:{{ 'hello'|capitalize }}</p> 12 {# 模板中处于安全考虑,默认情况下,会把标签进行转义,即把<>这个转成 <> #} 13 {# 但是在 开发中,我们有时候需要使用标签展示 ,需要禁止转义 #} 14 <p>禁止转义:{{ '<h1>黑马程序员</h1>'|safe }}</p> 15 <p>单词大写:{{ 'hello'|upper }}</p> 16 <p>单词小写:{{ 'HELLO'|lower }}</p> 17 <p>单词反转:{{ 'hello'|reverse }}</p> 18 <p>每个单词的首字母大写:{{ 'hello world!'|title }}</p> 19 <hr> 20 21 <h1>列表操作:</h1> 22 <p>获取列表中的第一个元素:{{ [1,2,3,4,5,6]|first }}</p> 23 <p>获取列表中的最后一个元素:{{ [1,2,3,4,5,6]|last }}</p> 24 <p>列表求和:{{ [1,2,3,4,5,6]|sum }}</p> 25 <p>列表排序:{{ [11,21,3,4,5,6]|sort }}</p> 26 <hr> 27 28 29 30 </body> 31 </html>
自定义过滤器:
1 from flask import Flask, render_template 2 3 app = Flask(__name__) 4 5 """ 6 过滤器本质就是一个函数. 7 内置的无法满足需求 8 自定义过滤器实际上就是写自定义函数 9 10 app.add_template_filter(do_setup2, 'xx'): 11 1.先定义一个函数 12 2.添加函数名do_setup2到flask的app对象里面,把过滤器函数名字'xx'传给模板文件 13 3.在模板文件中取出过滤器函数名字 'xx' 14 15 注意:在模板中只是使用过滤器,并不能自定义过滤器,自定义是在.py文件中进行 16 """ 17 18 19 # pycharm原生格式化代码:ctrl + alt + l 20 # 目前自己使用的:shift + alt + f 21 22 @app.route('/') 23 def index(): 24 return render_template('demo3.html') 25 26 27 # 自定义filter,每隔一个切割一次 28 def do_setup2(my_list): 29 # my_list是前端传来的数据 [11,21,3,4,5,6,9] 30 return my_list[::2] 31 32 33 # 在模板里面添加一个过滤器 34 # 第一个参数:表示自定义函数的名字, 35 # 第二个参数:表示在模板里面使用的过滤器的名字 36 app.add_template_filter(do_setup2, 'xx') 37 38 if __name__ == '__main__': 39 app.run()
对应的HTML:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>自定义filter</title> 6 </head> 7 <body> 8 {#{{ xx:自定义 }}#} 9 <p>对列表进行切片:{{ [11,21,3,4,5,6,9]|xx }}</p> 10 </body> 11 </html>
控制代码块:
1 from flask import Flask, render_template 2 3 app = Flask(__name__) 4 5 """ 6 控制代码块主要包含两个: 7 - if/else if /else / endif 8 - for / endfor 9 """ 10 11 12 @app.route('/') 13 def index(): 14 my_list = [ 15 { 16 "id": 1, 17 "value": "我爱工作" 18 }, 19 { 20 "id": 2, 21 "value": "工作使人快乐" 22 }, 23 { 24 "id": 3, 25 "value": "沉迷于工作无法自拔" 26 }, 27 { 28 "id": 4, 29 "value": "日渐消瘦" 30 }, 31 { 32 "id": 5, 33 "value": "以梦为马,越骑越傻" 34 } 35 ] 36 return render_template('demo4.html', my_list=my_list) 37 38 39 if __name__ == '__main__': 40 app.run(debug=True)
对应的HTML:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>控制代码块</title> 6 </head> 7 <body> 8 <h1>控制语句</h1> 9 {# 专门给for循环使用 loop.....#} 10 {% for item in my_list %} 11 {% if loop.index==1 %} 12 <li style="background-color: deeppink">{{ item.value }}</li> 13 {% elif loop.index==2 %} 14 <li style="background-color:greenyellow">{{ item.value }}</li> 15 {# 注意: else loop.index==3 这样是错误的写法,jinja2模板语法会报错: jinja2.exceptions.TemplateSyntaxError: expected token 'end of statement block', got 'loop' 16 正确写法: {% else %} else就是表示最后一个了,不再需要加loop.index进行判断 17 #} 18 {% else %} 19 <li style="background-color:red">{{ item.value }}</li> 20 {% endif %} 21 {% endfor %} 22 23 24 </body> 25 </html>
发送消息flash:
1 from flask import Flask, flash, render_template 2 3 """ 4 flash:作用:表示发送消息,往队列里面发送 5 flash是闪电的意思 6 7 类似前端里面的提示消息 8 9 使用场景: 10 在页面需要展示后端发送过来的消息的时候,进行使用,提示用户 11 12 13 扩展: 14 1.因为在发送消息的时候使用session,会存储一些隐私数据,比如购物车,为了安全起见, 15 在flask中如果使用到session,都必须加密,使用secret_key进行加密 16 """ 17 18 app = Flask(__name__) 19 20 # 加密口令,config['SECRET_KEY'] 注意:config里面的key必须大写 21 # ['SECRET_KEY'] 必须遵循config配置文件中默认的写法 22 # RuntimeError: the session is unavailable because no secret key was set. 23 # Set the secret_key on the application to something unique and secret. 24 # 设置秘钥不能为空,否则报错 25 # app.config['SECRET_KEY'] = '' 26 # 专业术语叫salt加盐 27 app.config['SECRET_KEY'] = 'shdfsjk' 28 29 # 加密之后再加密,再加密,至少十几次。银行密码6位数字的情况下。 30 # 专业术语叫做:加盐salt 加密 31 """ 32 常用的加密算法:MD5,SHA1,BASE64等等 33 注意:MD5是不可逆的,即MD5加密之后,不会反向破解出来 34 35 撞库: 36 37 """ 38 39 40 @app.route('/') 41 def index(): 42 # 内置对象,不需要传递 43 flash("用户名不正确") 44 flash("用户名不正确") 45 flash("用户名不正确") 46 flash("用户名不正确") 47 return render_template('demo6.html') 48 49 50 if __name__ == '__main__': 51 app.run(debug=True)
对应的HTML:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 {# get_flashed_messages 这是一个函数地址,加()才是一个函数,返回值是flashes 9 10 具体作用:Pulls all flashed messages from the session and returns them. 11 #} 12 {% for msg in get_flashed_messages() %} 13 <p>{{ msg }}</p> 14 {% endfor %} 15 16 </body> 17 </html>
message消息:
1 from flask import Flask, flash,render_template, request, get_flashed_messages 2 3 """ 4 get_flashed_messages(): 5 6 message是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除 7 用来存放临时值 8 """ 9 app = Flask(__name__) 10 app.secret_key = 'some_secret' 11 12 13 @app.route('/') 14 def index1(): 15 # 12.获取消息 16 v = get_flashed_messages() 17 print(v) 18 return render_template('index1.html') 19 20 21 # 设置完之后,只能通过浏览器访问一次刚刚设置的值,访问完之后就不能再第二次访问了 22 @app.route('/set') 23 def index2(): 24 v = request.args.get('p') 25 # 设置设置消息 26 flash(v) 27 return 'ok' 28 29 30 if __name__ == "__main__": 31 app.run()
对应的HTML:
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <h1>这是index1页面</h1> 9 {% with messages = get_flashed_messages() %} 10 {% if messages %} 11 <ul class=flashes> 12 {% for message in messages %} 13 <li>{{ message }}</li> 14 {% endfor %} 15 </ul> 16 {% endif %} 17 {% endwith %} 18 </body> 19 </html>
模板继承:
1 from flask import Flask,render_template 2 3 """ 4 模板继承:复用 5 6 如果子类需要继承父类,就在父类加一个block 7 8 {% block content %} 9 10 {% endblock %} 11 12 13 子类需要继承父类: 14 15 {% block content %} 16 <h1>子类的内容</h1> 17 {% endblock %} 18 19 20 需要注意:block里面的内容,子类和父类必须保证一样,用来识别是哪一个内容被修改 21 22 23 24 在子类中写{% extends "demo8_father.html" %}, 25 如果子类和父类数据不一样,添加block ... 26 """ 27 28 app = Flask(__name__) 29 30 31 @app.route('/') 32 def index(): 33 return render_template('demo7_son.html') 34 35 36 if __name__ == '__main__': 37 app.run()
对应的HTML:
demo7_son:
1 {% extends "demo8_father.html" %} 2 3 {% block content %} 4 <h1>子类的内容页面</h1> 5 {% endblock %}
demo8_father:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>父类的顶部</h1> 9 10 {% block content %} 11 <h1>父类的内容</h1> 12 {% endblock %} 13 14 <h1>父类的底部</h1> 15 </body> 16 </html>
命令行方式执行程序:
1 from flask import Flask 2 from flask_script import Manager 3 4 # Manager可以用来管理我们的应用程序 5 app = Flask(__name__) 6 # 创建一个flask的脚本,传输一个flask对象,把app对象交给manager管理 注意:需要传参数app 7 manager = Manager(app) 8 """ 9 因为公司里面都是脚本命令行操作 10 """ 11 12 13 @app.route('/') 14 def index(): 15 # index是视图函数 16 return 'index' 17 18 19 if __name__ == '__main__': 20 manager.run() 21
内置对象:
1 from flask import Flask, render_template, g, url_for 2 3 app = Flask(__name__) 4 5 """ 6 g变量就是一个容器,内置对象,不需要手动传 7 8 内置对象: 9 作用:如果使用内置对象,就不需要手动传递值,直接在页面上面使用即可 10 只是为了方便取值. 11 因为在模板页面里面已经把这些变量定义好了 12 13 g表示一个容器,里面可以存储值 14 格式: g.变量名 其中变量名可以随便取 15 """ 16 17 18 @app.route('/') 19 def index(): 20 g.name = 'heima' 21 return render_template('demo5.html') 22 23 24 if __name__ == '__main__': 25 app.run()
对应的HTML:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>特有内置对象</h1> 9 <p>获取内置的debug对象:{{ config.DEBUG }}</p> 10 <p>获取内置的请求的url:{{ request.url }}</p> 11 <p>获取内置的url_for对象:{{ url_for.url }}</p> 12 <p>获取内置的g变量里面的数据:{{ g.name }}</p> 13 </body> 14 </html>
内置的config默认信息: