实现结果:
Flask框架安装:
要使用Flask框架,需先在Python环境(官方文档推荐的做法是为Flask项目创建一个Python虚拟环境,在PyCharm工具中安装Python虚拟环境,使用pip命令安装的语法为:
pip install flask
为在PyCharm中的terminal终端中安装Flask框架的截图(注:图中的命令中使用了-i参数指定镜像源地址)。如果安装成功,将会在终端窗口看到一条“Successfully installed…”的输出信息。Flask应用创建
Flask框架安装后,便可以开始使用它来构建web应用。如图5所示是参考官方入门文档中的介绍而创建的一个简单Flask应用:
上述代码实现了如下功能:
- 首先导入了 Flask 类。该类的实例将会成为我们的 WSGI 应用(WSGI : Web Server Gateway Interface, Web服务器网关接口。具体的来说,WSGI是一个规范,定义了Web服务器如何与Python应用程序进行交互,使得使用Python写的Web应用程序可以和Web服务器对接起来)。
- 接着创建一个Flask类的实例。第一个参数是应用模块或者包的名称。__name__ 是一个适用于大多数情况的快捷方式。有了这个参数,Flask 才能知道在哪里可以找到模板和静态文件等内容。
- 使用route() 装饰器来设置路由规则,告诉 Flask 触发某个视图函数的URL。在本示例中,route()装饰器中的参数“/”告诉Flask应用程序,当用户访问网站的根目录(即URL为'/')时运行hello_world()这个函数。
- 在视图函数中返回需要在用户浏览器中显示的信息。默认的内容类型是 HTML,因此字符串中的 HTML标签会被浏览器渲染。
Flask应用创建后,可在Terminal终端中输入命令运行应用,格式如下:
flask --app 模块名 run
输入运行命令后回车在图6中所示的终端中单击链接地址(如:http://127.0.0.1:5000),或直接在浏览器地址栏中输入相应的URL(如:http://127.0.0.1:5000),应该能在浏览器界面中看到一行文本:“Hello World!”,如图7所示:说明:图6中的命令会启动一个非常简单的内建的服务器。从截图中的输出信息可知,这个服务器应该仅用于开发测试,不适合用于生产部署。生产部署时应该选择诸如Gunicorn、uWSGI等标准WSGI服务器。
也可以修改对应的模块,通过调用Flask对象的run()方法启动服务,如图8所示:说明:图8中的第12代码通过Flask对象app的run方法启动服务,通过参数host指定主机,port参数指定运行的端口号,debug=True设置程序运行于调试模式下,可在终端及web页面中输出相关的调试信息。
模板渲染
图8所示的代码中,函数hello_world()直接返回了一个HTML字符串,这种直接在Python代码中编写HTML文档的方法非常笨拙,并且开发人员必须自己负责HTML的转义,以确保应用的安全。因此,必须使用一种优雅高效的方式来完成HTML页面的渲染工作,Flask使用Jinja2模板引擎来负责处理这项工作。通过预先编写好的模板文件(一个文本文件,可以为HTML、XML等格式文件,其中利用Jinja2模板语法指定要动态填入的相关内容,以最终渲染成一个完成的HTML页面或其它合适的文档),在视图函数被调用时,将模板名称和需要传递给模板的变量作为参数,传递给Flask框架提供的render_template()方法以用于渲染模板。
Flask 会在templates文件夹内寻找模板。因此,如果Flask应用是一个模块,那么模板文件夹应该在模块旁边;如果是一个包,那么就应该在包里面。接下来,让我们通过一个示例来具体看看Flask的模板渲染。
- 在图5所示的hello_flask项目中与hello_flask.py模块同级目录下(即项目的根目录),创建一个templates文件夹,如图9所示:
- 在templates文件夹下创建一个模板文件index.html,并输入如图10中所示的代码:
-
重新运行hello_flask.py,并打开对应的浏览器页面,应该能看到如图12中所示的页面内容:静态文件
在一个动态的web应用中通常会需要一些静态文件,如 CSS 样式文件、 JavaScript脚本文件或其它的一些图标图像文件等。Flask应用默认的静态文件位于应用的 /static 目录中。在模板文件中,可以通过url_for()方法并使用特定的“static”参数来生成相应静态文件的URL,例如要获取/static目录下的style.css文件,则url_for()的调用格式如下:
url_for('static', filename='style.css')
下面通过一个示例来练习Flask应用中对静态文件的引用:
- 在图5所示的hello_flask项目的根目录下,创建一个static文件夹,并在static文件夹下创建三个子文件夹:css、js、images,然后在css文件夹中新建一个cz_style.css文件,在js文件夹中新建一个cz_exam.js文件,在images文件夹中放入一张名为cz_bar.jpg的图片,如图13所示:
- 编辑cz_style.css文件,输入如图14所示的内容:
.center-div{ width: 50%; /* 设置宽度为50%,使元素水平居中 */ margin: 0 auto; /* 水平居中 */ padding: 20px; /* 内边距为20px */ border: 1px solid #000; /* 边框为1px实线,颜色为黑色 */ border-radius:10px; /* 圆角为10px */ } .cz-stem { font-size:16px; /* 字体大小为16px */ font-weight: bolder; /* 设置字体为粗体 */ margin:10px; /* 外边距为10px */ } .cz-choice { font-size:14px; /* 字体大小为14px */ margin:10px 20px; /* 设置外边距,上下为10px,左右为20px */ } .cz-btn { font-size:14px; /* 字体大小为14px */ margin-top:20px; /* 上外边距为20px */ padding:5px 25px; /* 设置内边距,上下为5px,左右为25px */ color:white; /* 设置前景色为白色 */ background-color:#007BFF; /* 设置背景色为蓝色 */ border: none; /* 隐藏边框 */ border-radius:4px; /* 设置圆角为4px */ cursor: pointer; /* 设置指针样式 */ display: block; /* 块级元素 */ margin-left: auto; /* 自动左边距,使按钮向右对齐 */ } .cz-btn:hover { /* 定义一个:hover伪类用于改变鼠标悬停在按钮上时的背 */ background-color:#0056b3; /*设置背景色 */ } .cz-bar{ width: 100%; /* 设置宽度为100%,匹配父元素的宽度*/ margin-top:20px; /* 上外边距为20px */ border-radius:3px; /* 圆角为10px */ }
说明:cz_style.css中定义了将要后续的exam.html模板文件使用的相关类样式。
- 编辑cz_exam.js文件,输入如图15所示的内容。在cz_exam.js中,使用JavaScript语言实现对exam.html中的form表单的submit事件的捕获处理,在事件处理方法中取消了form表单的默认提交行为,改为用fetch方法(现代浏览器中内置的实现AJAX异步操作的方法)实现与Flask视图函数的交互,在不刷新页面的情况下实现数据的更新。
document.getElementById('myForm').addEventListener('submit', function(event) { // 阻止表单默认的提交行为 event.preventDefault(); // 使用 fetch 异步提交表单数据 fetch('/exam', { method: 'POST', body: JSON.stringify({"leader": event.target.leader.value}), headers: {'Content-Type': 'application/json'} }) .then(response => response.json()) // 解析 JSON 响应 .then(data => { if (data.msg == 'ok') { alert("回答正确!"); } else { alert("抱歉,回答错误,赶紧补补历史知识吧!"); } }); });
- 在templates文件夹下创建一个模板文件exam.html,并输入如图16中所示的代码。在图16中的第6行、第17行、第20行处分别通过url_for方法构造出了对应的静态文件:cz_style.css、cz_bar.jpg、cz_exam.js的正确URL,以确保页面渲染时能加载到相应的静态文件。代码中的{% … %}和{{ … }}为Jinja2模板引擎中的相关语法,将在下一实训中进行介绍。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{{Title}}</title> <link rel="stylesheet" href="{{ url_for('static', filename='css/cz_style.css') }}"> </head> <body> <div class="center-div"> <div id="stem" class="cz-stem">{{ question.stem }}</div> <form id="myForm" action="/exam" method="POST"> {% for option in question.options %} <input type="radio" class="cz-choice" name="leader" value="{{ loop.index }}">{{ option }}<br> {% endfor %} <input type="submit" class="cz-btn" value="提交"> </form> <img src="{{ url_for('static', filename='images/cz_bar.jpg') }}" class="cz-bar"> </div> <script src="{{ url_for('static', filename='js/cz_exam.js') }}"></script> </body> </html>
- 修改hello_flask.py文件,新添加一个视图函数examine(),如图17所示。
# hello_flask.py from flask import Flask,render_template,request,jsonify app = Flask(__name__) @app.route('/') def hello(): title = "长征" info ="长征的英文是: Long March" return render_template("index.html", title=title, info=info) @app.route("/exam",methods=['GET','POST']) def examine(): title ="长征" question = { "stem":"1934年10月,时任中共中央总书记的是:", "options":["毛泽东","周恩来","李德","博古"], "answer":4 } if request.method =='POST': result =request.json.get("leader") #从请求中获取JSON数据 data ={'msg':'error'} if result and question.get('answer') == int(result): data['msg']='ok' return jsonify(data) else: return render_template("exam.html", title=title, question=question) if __name__ == '__main__': # app.run() app.run(debug = True , host='0.0.0.0' , port = 9999)
- 重新运行hello_flask.py,在浏览器地址栏中输入相应地址(如:http://127.0.0.1:9999/exam)打开对应页面,应该能看到如图18中所示的页面内容。
- 在页面中选择对应选项后,单击提交按钮,应该能看到答题的反馈结果,如图19所示。