首先我们在项目的根目录下创建一个 Python 虚拟环境,打开命令行输入以下指令:
python -m venv venv
启动虚拟环境:
.\venv\Scripts\Activate.ps1
如果遇到报错:.\venv\Scripts\Activate.ps1 : File ...\venv\Scripts\Activate.ps1 cannot be loaded because running scripts is disabled on this system.,说明可能是系统禁止运行脚本,打开 PowerShell 查看一下系统当前的执行策略:
get-executionpolicy
如果为 Restricted 说明此系统不载入任何配置文件,不运行任何脚本。我们需要修改一下执行策略,以管理员身份打开 PowerShell,使用以下指令修改执行策略:
Set-ExecutionPolicy Unrestricted # 设置全局的执行策略
Set-ExecutionPolicy -Scope CurrentUser Unrestricted # 设置当前用户的执行策略
接下来我们安装 Flask:
pip install flask
我们先看一下如何创建 URL 与函数的对应关系:
from flask import Flask
app = Flask(__name__) # 实例化Flask类的对象
@app.route("/index")
def index():
return "Hello World!
"
if __name__ == "__main__":
app.run()
其中的 @app.route 作用是创建了网址 /index 与 index 函数的对应关系。现在我们运行程序,能看到终端的输出: * Running on http://127.0.0.1:5000,然后我们访问 http://127.0.0.1:5000/index 即可看到 Hello World!。
app.run() 方法中有以下几个参数:
host:主机名,默认为 127.0.0.1(即 localhost)。port:端口号,默认为5000。debug:是否开启 DEBUG 模式,默认为 False,开启后每次对代码进行修改保存后直接刷新网页即可实时显示效果,否则需要手动重启项目才能看到改动。注意我们返回的字符串中有 标签,这是 HTML 标签,整个项目的逻辑是用户(浏览器)访问 URL 时向 Web 应用(此处就是 Flask)发送请求,然后 Web 应用向浏览器返回一个字符串,浏览器是具备解析 这类 HTML 标签的能力的。前端部分的学习可以在 Web 专栏中找到。
Tips:PyCharm 输入 main 即可自动补全出 if __name__ == "__main__":,VS Code 则需要进行配置,点击左下角的齿轮,选择 User Snippets(用户代码片段),然后在弹出的下拉选框中选择 python,这时会出来一个配置文件 python.json,然后向该文件中添加 "Print to console" 项,修改后如下:
{
"Print to console": {
"prefix": "main",
"body": [
"if __name__ == '__main__':",
" ${1:pass}",
"",
],
"description": "python--main"
}
}
Flask 框架为了让我们写 HTML 标签更方便,支持将这些内容写到一个单独的文件中,render_template 函数可以渲染 HTML 文件,默认是从项目根目录下的 templates 目录中开始寻找文件,我们创建 templates 目录并创建一个 index.html 如下:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Indextitle>
head>
<body>
<h1>Hello World!h1>
body>
html>
现在就可以将之前的字符串改为渲染一个 HTML 文件了:
from flask import Flask, render_template
app = Flask(__name__) # 实例化Flask类的对象
@app.route("/index")
def index():
return render_template("index.html")
if __name__ == "__main__":
app.run()
假设我们在页面中需要引入一张本地的图片,在 Flask 中要求我们需要将图片这类静态文件(还有视频、音频、CSS、JS 等)放在项目根目录中的 static 目录下,假设我们有一张图片放在 static/image 目录下,那么就可以直接用相对路径调用该图片了:
DOCTYPE html>
<html lang="en">
...
<body>
<h1>Hello World!h1>
<img src="/static/image/background.jpg" />
body>
html>
假设我们需要实现一个注册页面,那么浏览器就需要将用户输入的信息发送到后端服务器,发送请求的方式有 GET 和 POST,这两种方式的主要区别如下:
@app.route 有一个参数叫做 methods,表示前端访问该 URL 时发送请求的方式,例如 methods=['GET'] 表示浏览器只能用 GET 请求方式访问该 URL。
我们假设现在有一个用于注册的前端页面 register.html,其中有两个表单分别为 GET 请求和 POST 请求:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registertitle>
head>
<body>
<h1>Registerh1>
<hr>
<form method="get" action="/register/get">
<fieldset>
<legend>GET Formlegend>
<label for="get_username">账号:label>
<input type="text" name="username" id="get_username" placeholder="Please input username">
<br>
<label for="get_password">密码:label>
<input type="password" name="password" id="get_password" placeholder="Please input password">
<br>
<button type="subimt" id="get_submit">GET Submitbutton>
fieldset>
form>
<hr>
<form method="post" action="/register/post">
<fieldset>
<legend>POST Formlegend>
<label for="post_username">账号:label>
<input type="text" name="username" id="post_username" placeholder="Please input username">
<br>
<label for="post_password">密码:label>
<input type="password" name="password" id="post_password" placeholder="Please input password">
<br>
<button type="subimt" id="post_submit">POST Submitbutton>
fieldset>
form>
body>
html>
我们在 Flask 后端可以通过 request 接收前端提交过来的表单的内容:
from flask import Flask, render_template, request
app = Flask(__name__) # 实例化Flask类的对象
@app.route("/register")
def register():
return render_template("register.html")
@app.route("/register/get", methods=["GET"])
def register_get():
print(request.args) # GET请求的内容在args中
print(request.args.get("username")) # 获取username,如果有多个数据用getlist
return "GET Register"
@app.route("/register/post", methods=["POST"])
def register_post():
print(request.form) # POST请求的内容在form中
print(request.form.get("username"))
return "POST Register"
if __name__ == "__main__":
app.run()
通过 GET 方式提交的表单 URL 为:http://127.0.0.1:5000/register/get?username=AsanoSaki&password=123456,而通过 POST 方式提交的表单 URL 为:http://127.0.0.1:5000/register/post。
后端的输出内容如下:
ImmutableMultiDict([('username', 'AsanoSaki'), ('password', '123456')]) # GET
ImmutableMultiDict([('username', 'AsanoSaki'), ('password', '123456')]) # POST
由于我们的 /request/post 地址只支持 POST 请求,因此如果直接输入地址访问的话将会提示 The method is not allowed for the requested URL.。现在我们假设注册只用 POST 请求,那么我们就可以将 /request/post 的内容合并到 /request 中,然后判断前端发来的请求如果为 GET 就渲染 register.html,如果为 POST 就接收表单信息:
from flask import Flask, render_template, request
app = Flask(__name__) # 实例化Flask类的对象
@app.route("/register", methods=["GET", "POST"])
def register():
if request.method == "GET":
return render_template("register.html")
elif request.method == "POST":
print(request.form) # POST请求的内容在form中
print(request.form.get("username"))
return "POST Register"
if __name__ == "__main__":
app.run()
对应的 register.html 如下:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registertitle>
head>
<body>
<h1>Registerh1>
<hr>
<form method="post" action="/register">
<fieldset>
<legend>POST Formlegend>
<label for="post_username">账号:label>
<input type="text" name="username" id="post_username" placeholder="Please input username">
<br>
<label for="post_password">密码:label>
<input type="password" name="password" id="post_password" placeholder="Please input password">
<br>
<button type="subimt" id="post_submit">POST Submitbutton>
fieldset>
form>
body>
html>