写在前面
Flask是一个使用 Python 编写的轻量级 Web 应用框架。Flask对比Django框架灵活度更高了,可以自己一些设计代码框架,可以说他是短小精悍。
学习flask框架的目的是给自己的网页做一个后台系统、搭建属于自己的api系统,这也是我学习这款框架的原因。
下面我们开始正题
配置环境
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple Flask
创建项目文件
这里我是用的开发软件是Visual Studio Code
首先在在存放项目的位置新建这样几个文件
目录结构为
pyflask --app ----templates ------index.html ----__init__.py ----routes.py --run.py
然后右击项目文件夹pyflask使用vscode打开
这里我就犯过这种错误,如果不以文件夹的方式打开项目最终程序会因为找不到路径报错
Hello Flask
然后我们分别给每个文件填上以下代码
init.py
# 这里注意导包的顺序不能错乱 from flask import Flask # 创建app应用,__name__是python预定义变量,被设置为使用本模块. app = Flask(__name__) from app import routes
routes.py
# 从app模块中即从__init__.py中导入创建的app应用 from app import app @app.route('/') def getIndex(): return 'Hello Flask!'
run.py : 这里我们需要了解的地方是app.run()这个函数
debug参数开启后文件发生改变及时重启服务器
关闭后需要手动重启服务器内容才会发生改变
host为ip地址默认为以下参数,然后我们通过127.0.0.1即可访问
port参数为访问端口
# 从app模块中导入app应用 from app import app # 防止被引用后执行,只有在当前模块中才可以使用 if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=3000)
index.html(这里我们还用不到,但是后面的返回网页需要使用)
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>这个是我的标题</title> </head> <body> 这里是我的网页内容 </body> </html>
然后我们运行run.py出现以下信息表明运行成功这个使用我们访问
win:http://127.0.0.1:3000/ 或者 http://localhost:3000/
linux:http://localhost:3000/
然后我们就会看到以下结果 恭喜你已经完整搭建好了flask框架!
通过代码我们可以看到我们前台的数据和routes.py文件中的函数返回的内容相同,是的我们的内容确实是来源于routes.py也就是路由,读者可以自行尝试更改return的内容来测试前台数据的变化。
下面我们使用flask框架返回一个网页试试
请求方式GET与POST
在信息输出创口我们可以看到我们通过浏览器访问数据是使用的get请求,如果我们要实现post访问的测试我们需要用到一个软件
然后我们使用get请求再试一下前面的测试
返回没有问题,然后我们使用post请求测试以下
我们可以看到网页返回了一个405错误
然后我们这里引入新的知识,访问方式在routes.py中修改内容为
# 从app模块中即从__init__.py中导入创建的app应用 from app import app @app.route("/", methods=["GET", "POST"]) def getIndex(): return 'Hello Flask!'
这里我们给app.route()中添加了一个methods参数这个参数表示该路由接口可以使用GET和POST两种方式请求,下面我们实现一个post和get请求分别返回不同内容的例子
在routes.py中修改
from app import app from flask import request # 判断get还是post请求 @app.route("/", methods=("GET", "POST")) def getIndex(): if request.method == "POST": return "post flask" else: return 'Hello Flask!'
然后我们再使用工具测试一下
下面我们开始实现返回一个网页试试
返回一个网页
这里我们就要用到前面创建的templates文件夹了(其实主要还是要用文件夹下面的html文件)
然后我们在routes文件中新建一个路由,并引用返回html的模块,具体内容如下:
from app import app from flask import request # 判断get还是post请求 from flask import render_template # 读取template中的网页文件 @app.route("/", methods=("GET", "POST")) def getIndex(): if request.method == "POST": return "post flask" else: return 'Hello Flask!' @app.route("/index") def getHtml(): return render_template('index.html')
然后我们通过浏览器访问可以得到以下内容
发送数据到前台
然后我们来实现通过后台修改前台数据内容,这里展示两种方式实现:
方式一:
routes.py
@app.route("/index/<title>") def getHtml(title): return render_template('index.html', title=title)
index.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>{{title}}</title> </head> <body> 这里是我的网页内容 </body> </html>
效果
方式二:
@app.route("/test") def getTest(): title = "情人节快乐" return render_template('index.html', title=title)
沿用方式一的index页面内容即可
再index文件中其实我们也可以使用判断语句以及for语句,具体使用方法如下
{% if text %} <h1>传入得内容为{{ text}}!</h1> {% else %} <h1>未传入内容</h1> {% endif %}
在html中使用{{ 变量 }}来接受后台传入的数据
使用{% 语句 %}来循环和判断语句
这里我的代码为
routes.py
from app import app from flask import request # 判断get还是post请求 from flask import render_template # 读取template中的网页文件 @app.route("/", methods=("GET", "POST")) def getIndex(): if request.method == "POST": return "post flask" else: return 'Hello Flask!' @app.route("/index/<title>") def getHtml(title): return render_template('index.html', title=title) @app.route("/test/") @app.route("/test/<text>") def getTest(text=None): title = "情人节快乐" return render_template('index.html', title=title, text=text)
index.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>{{title}}</title> </head> <body> {% if text %} <h1>传入得内容为{{ text }}!</h1> {% else %} <h1>未传入内容</h1> {% endif %} </body> </html>
获取前台数据
这里我们就会用到post请求方式,get又称为显示请求,post称为隐示请求,如果我们写一个网站把账号密码显示到浏览地址是不是总觉得不安全吧,所以我们这里需要使用到post请求,但是post请求也不是绝对安全,但是我们在数据传输得过程中肯定是要使用post请求得,这样必get肯定安全不少,下面看示例:
这里我们在templates文件夹下面添加一个login.html文件内容如下:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>登录页面</title> </head> <body> <form align="center" action="#" method="post"> username:<input type="text" name="username"/> </br> password:<input type="password" name="password"/></br> <button type="submit">登录</button></br> {{ msg }} </form> </body> </html>
然后再路由文件夹下面添加
@app.route("/login", methods=['GET', 'POST']) def login(): #方式1 # user_info = request.form.to_dict() # if user_info.get("username") == "admin" and user_info.get("password") == '123456': # return redirect("/") #方式2 username = request.form.get("username") password = request.form.get("password") if username == "admin" and password == "123456": return render_template("index.html", title="登录成功") elif request.method == 'GET': return render_template("login.html") else: return render_template("login.html", msg="账号密码错误")
然后我们测试账号密码登录:账号密码错误提示
账号密码正确提示
这里我们要获取前端传给我们得数据就需要使用到request.form.get(“变量名”)函数
前端传给后端数据需要使用到提交按钮以及数据块
上传文件到后端
新建一个file页面内容为:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>文件上传</title> </head> <body> <form align = "center" action="#" method="post" enctype="multipart/form-data"> 文件:<input type="file" name="files"> <button type="submit">上传</button> </form> </body> </html>
新建一个路由内容为:
@app.route("/file", methods=("GET", "POST")) def updateFile(): if request.method == "POST": # 获取上传文件数据 file = request.files.get('files') # 保存文件到根目录 file.save(file.filename) return render_template("file.html") else: return render_template("file.html")
实现效果
到这里我们就实现了Flask框架的前后端变量传送,文件上传,网页返回内容,更多得知识需要阅读开发手册进行查看!下面我们来通过已学得知识来做一个简单的登录页面
实战:实现一个简单的登录页面
init.py
# 这里注意导包的顺序不能错乱 from flask import Flask # 创建app应用,__name__是python预定义变量,被设置为使用本模块. app = Flask(__name__) from app import routes
templates文件中得index文件
Index.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>巴拉巴拉巴拉~~~~我也不知道取什么</title> <link rel="stylesheet" href="static/css/style.css"> </head> <body> <div class="content"> <div class="form sign-in"> <h2>欢迎回来</h2> <form action="#" method="post"> <label> <span>用户名</span> <input type="text" name="username" /> </label> <label> <span>密码</span> <input type="password" name="userpwd" /> </label> <!-- <p class="forgot-pass"><a href="javascript:">忘记密码?</a></p> --> <button type="submit" class="submit">登 录</button> <label><span>{{msg}}</span></label> </form> </div> <div class="sub-cont"> <div class="img"> <div class="img__text m--up"> <h2>还未注册?</h2> <p>立即注册,发现大量机会!</p> </div> <div class="img__text m--in"> <h2>已有帐号?</h2> <p>有帐号就登录吧,好久不见了!</p> </div> <div class="img__btn"> <span class="m--up">注 册</span> <span class="m--in">登 录</span> </div> </div> <div class="form sign-up"> <h2>立即注册</h2> <form action="#" method="post"> <label> <span>用户名</span> <input type="text" name="name" /> </label> <!-- <label> <span>邮箱</span> <input type="email" /> </label> --> <label> <span>密码</span> <input type="password" name="pwd" /> </label> <button type="submit" class="submit">注 册</button> </form> </div> </div> </div> <script src="static/js/script.js"></script> </body> </html>
然后我们再在工程文件中新建一个static文件夹用来存放网页得静态文件(js,css,img)
目录结构:
static
js
script.js
css
stylle.css
images
bg.jpg
stylle.css
*, *:before, *:after { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: "Open Sans", Helvetica, Arial, sans-serif; background: #ededed; } input, button { border: none; outline: none; background: none; font-family: "Open Sans", Helvetica, Arial, sans-serif; } .tip { font-size: 20px; margin: 40px auto 50px; text-align: center; } .content { overflow: hidden; position: absolute; left: 50%; top: 50%; width: 900px; height: 550px; margin: -300px 0 0 -450px; background: #fff; } .form { position: relative; width: 640px; height: 100%; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; padding: 100px 30px 0; } .sub-cont { overflow: hidden; position: absolute; left: 640px; top: 0; width: 900px; height: 100%; padding-left: 260px; background: #fff; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; } .content.s--signup .sub-cont { -webkit-transform: translate3d(-640px, 0, 0); transform: translate3d(-640px, 0, 0); } button { display: block; margin: 0 auto; width: 260px; height: 36px; border-radius: 30px; color: #fff; font-size: 15px; cursor: pointer; } .img { overflow: hidden; z-index: 2; position: absolute; left: 0; top: 0; width: 260px; height: 100%; padding-top: 360px; } .img:before { content: ""; position: absolute; right: 0; top: 0; width: 900px; height: 100%; background-image: url(../images/bg.jpg); background-size: cover; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; } .img:after { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.6); } .content.s--signup .img:before { -webkit-transform: translate3d(640px, 0, 0); transform: translate3d(640px, 0, 0); } .img__text { z-index: 2; position: absolute; left: 0; top: 50px; width: 100%; padding: 0 20px; text-align: center; color: #fff; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; } .img__text h2 { margin-bottom: 10px; font-weight: normal; } .img__text p { font-size: 14px; line-height: 1.5; } .content.s--signup .img__text.m--up { -webkit-transform: translateX(520px); transform: translateX(520px); } .img__text.m--in { -webkit-transform: translateX(-520px); transform: translateX(-520px); } .content.s--signup .img__text.m--in { -webkit-transform: translateX(0); transform: translateX(0); } .img__btn { overflow: hidden; z-index: 2; position: relative; width: 100px; height: 36px; margin: 0 auto; background: transparent; color: #fff; text-transform: uppercase; font-size: 15px; cursor: pointer; } .img__btn:after { content: ""; z-index: 2; position: absolute; left: 0; top: 0; width: 100%; height: 100%; border: 2px solid #fff; border-radius: 30px; } .img__btn span { position: absolute; left: 0; top: 0; display: flex; justify-content: center; align-items: center; width: 100%; height: 100%; transition: -webkit-transform 0.6s; transition: transform 0.6s; transition: transform 0.6s, -webkit-transform 0.6s; } .img__btn span.m--in { -webkit-transform: translateY(-72px); transform: translateY(-72px); } .content.s--signup .img__btn span.m--in { -webkit-transform: translateY(0); transform: translateY(0); } .content.s--signup .img__btn span.m--up { -webkit-transform: translateY(72px); transform: translateY(72px); } h2 { width: 100%; font-size: 26px; text-align: center; } label { display: block; width: 260px; margin: 25px auto 0; text-align: center; } label span { font-size: 12px; color: #909399; text-transform: uppercase; } input { display: block; width: 100%; margin-top: 5px; padding-bottom: 5px; font-size: 16px; border-bottom: 1px solid rgba(0, 0, 0, 0.4); text-align: center; } .forgot-pass { margin-top: 15px; text-align: center; font-size: 12px; color: #cfcfcf; } .forgot-pass a { color: #cfcfcf; } .submit { margin-top: 40px; margin-bottom: 20px; background: #d4af7a; text-transform: uppercase; } .fb-btn { border: 2px solid #d3dae9; color: #8fa1c7; } .fb-btn span { font-weight: bold; color: #455a81; } .sign-in { transition-timing-function: ease-out; } .content.s--signup .sign-in { transition-timing-function: ease-in-out; transition-duration: 0.3s; -webkit-transform: translate3d(640px, 0, 0); transform: translate3d(640px, 0, 0); } .sign-up { -webkit-transform: translate3d(-900px, 0, 0); transform: translate3d(-900px, 0, 0); } .content.s--signup .sign-up { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); }
script.js
document.querySelector('.img__btn').addEventListener('click', function() { document.querySelector('.content').classList.toggle('s--signup') })
bg.jpg
routes.py
# 从app模块中即从__init__.py中导入创建的app应用 from app import app from flask import render_template from flask import request # 建立路由,通过路由可以执行其覆盖的方法,可以多个路由指向同一个方法。 @app.route('/', methods=['POST', 'GET']) @app.route('/index', methods=['POST', 'GET']) def index(): username = request.form.get("username") userpwd = request.form.get("userpwd") if username == "stylle" and userpwd == "daikongjun": return render_template("user.html") elif request.method == 'GET': return render_template("index.html") else: return render_template("index.html", msg="登录失败") @app.route('/user') def getUser(): return render_template("user.html")
run.py
# 从app模块中导入app应用 from app import app # 防止被引用后执行,只有在当前模块中才可以使用 if __name__ == '__main__': app.run(host='0.0.0.0', port=80)
然后我们部署到服务器通过公网ip访问效果