Flask 是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器,本文将收集一些常用的开发小例子方便开发速查.
Web 框架的本质
实现简单HTTP: 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端,其下面就是简单实现的HTTP服务器.
import socket
def handle_request(client):
buf = client.recv(1024)
client.send(bytes("HTTP/1.1 200 OK\r\n\r\n","UTF-8"))
client.send(bytes("<b>Hello lyshark</b>","UTF-8"))
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("localhost",80))
sock.listen(5)
while True:
connection, address = sock.accept()
handle_request(connection)
connection.close()
if __name__ == "__main__":
main()
python wsgi接口 WSGI是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦,python标准库提供的独立WSGI服务器称为wsgiref
from wsgiref.simple_server import make_server
def RunServer(environ,start_response):
start_response("200 OK",[("Content-Type","text/html")])
print(environ['PATH_INFO'])
return [b"<h1>Hello lyshark</h1>"]
if __name__ == "__main__":
httpd = make_server("localhost",80,RunServer)
print("Serving HTTP on port 80...")
httpd.serve_forever()
Flask 表单操作
◆CheckBox 复选框◆
HTML index.html
<body>
<form action="/" method="post">
<div class="MyDiv">
<label>
<input type="checkbox" name="s_option" value="basketball" > 篮球
</label>
<label>
<input type="checkbox" name="s_option" value="football" > 足球
</label>
<label>
<input type="checkbox" name="s_option" value="badminton" > 羽毛球
</label>
</div>
<input type="submit" value="发送"/>
</form>
</body>
</html>
后台 app.py
from flask import Flask,render_template,request
app = Flask(__name__)
@app.route("/",methods=['POST','GET'])
def index():
if request.method == "POST":
data = request.values.getlist("s_option")
print("您的选择内容是: %s" %data)
return render_template("index.html")
if __name__ == '__main__':
app.run()
◆Select 选择框◆
HTML index.html
<body>
<form action="/" method="post">
<select name="MySelect">
<option selected="selected">--请选择厂家--</option>
<option >惠普</option>
<option >华为</option>
<option >戴尔</option>
</select>
<input type="submit" value="发送"/>
</form>
</body>
后台 app.py
from flask import Flask,render_template,request
app = Flask(__name__)
@app.route("/",methods=['POST','GET'])
def index():
if request.method == "POST":
data = request.values.get("MySelect")
print("您的选择内容是: %s" %data)
return render_template("index.html")
if __name__ == '__main__':
app.run()
Ajax 发送数据◆
HTML页面发送数据,后端接收并返回数据
HTML index.html
<body>
<input type="button" class="MyButton" value="发送数据" onclick="SendAjax()">
<script src="/static/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
function SendAjax(){
$.ajax({
url:"/dataFromAjax",
contentType: "POST",
data:{"MyData": "hello lyshark"},
success:function(data){
alert("返回数据:" + data);
},
error:function(){
alert("执行失败了...")
}
});
}
</script>
</body>
后台 app.py
from flask import Flask,render_template,request
from flask import jsonify
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/dataFromAjax")
def recv():
data = request.args.get("MyData")
print("收到客户端数据: %s"%data)
return "通信成功..."
if __name__ == '__main__':
app.run()
Ajax 获取数据◆
后端发送JSON数据,HTML页面接收数据并显示出来.
HTML index.html
<body>
<input type="button" class="MyButton" value="接收数据" onclick="GetAjax()">
<script src="/static/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
function GetAjax(){
$.ajax({
url:"/dataFromAjax",
contentType: "GET",
success:function(data){
alert("姓名: " + data.name + "年龄: " + data.age);
},
error:function(){
alert("执行失败了...")
}
});
}
</script>
</body>
后台 app.py
from flask import Flask,render_template,request
from flask import jsonify
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/dataFromAjax",methods=["GET","POST"])
def set():
data = {"name":"lyshark","age":"23"}
return jsonify(data)
# info = dict() //另一种组装发送数据的方法
# info['name'] = "lyshark"
# info['age'] = 22
# return jsonify(info)
if __name__ == '__main__':
app.run()
Flask 过滤器
字符串操作:
{# 当变量未定义时,显示默认字符串,可以缩写为d #}
<p>{{ name | default('No name', true) }}</p>
{# 单词首字母大写 #}
<p>{{ 'hello' | capitalize }}</p>
{# 单词全小写 #}
<p>{{ 'XML' | lower }}</p>
{# 去除字符串前后的空白字符 #}
<p>{{ ' hello ' | trim }}</p>
{# 字符串反转,返回"olleh" #}
<p>{{ 'hello' | reverse }}</p>
{# 格式化输出,返回"Number is 2" #}
<p>{{ '%s is %d' | format("Number", 2) }}</p>
{# 关闭HTML自动转义 #}
<p>{{ '<em>name</em>' | safe }}</p>
{% autoescape false %}
{# HTML转义,即使autoescape关了也转义,可以缩写为e #}
<p>{{ '<em>name</em>' | escape }}</p>
{% endautoescape %}
#用管道的形式,如果avatar(后端传过来的变量)的值不存在,则用default的值
{{ avatar|default('xxx') }}
#这里的意思为获取avatar的长度,avatar为后端传过来的变量,可以是列表,也可以是字典
{{ avatar|length }}
数值操作:
{# 四舍五入取整,返回13.0 #}
<p>{{ 12.8888 | round }}</p>
{# 向下截取到小数点后2位,返回12.88 #}
<p>{{ 12.8888 | round(2, 'floor') }}</p>
{# 绝对值,返回12 #}
<p>{{ -12 | abs }}</p>
列表操作:
{# 取第一个元素 #}
<p>{{ [1,2,3,4,5] | first }}</p>
{# 取最后一个元素 #}
<p>{{ [1,2,3,4,5] | last }}</p>
{# 返回列表长度,可以写为count #}
<p>{{ [1,2,3,4,5] | length }}</p>
{# 列表求和 #}
<p>{{ [1,2,3,4,5] | sum }}</p>
{# 列表排序,默认为升序 #}
<p>{{ [3,2,1,5,4] | sort }}</p>
{# 合并为字符串,返回"1 | 2 | 3 | 4 | 5" #}
<p>{{ [1,2,3,4,5] | join(' | ') }}</p>
{# 列表中所有元素都全大写。这里可以用upper,lower,但capitalize无效 #}
<p>{{ ['tom','bob','ada'] | upper }}</p>
字典列表操作:
{% set users=[{'name':'Tom','gender':'M','age':20},
{'name':'John','gender':'M','age':18},
{'name':'Mary','gender':'F','age':24},
{'name':'Bob','gender':'M','age':31},
{'name':'Lisa','gender':'F','age':19}]
%}
{# 按指定字段排序,这里设reverse为true使其按降序排 #}
<ul>
{% for user in users | sort(attribute='age', reverse=true) %}
<li>{{ user.name }}, {{ user.age }}</li>
{% endfor %}
</ul>
{# 列表分组,每组是一个子列表,组名就是分组项的值 #}
<ul>
{% for group in users|groupby('gender') %}
<li>{{ group.grouper }}<ul>
{% for user in group.list %}
<li>{{ user.name }}</li>
{% endfor %}</ul></li>
{% endfor %}
</ul>
{# 取字典中的某一项组成列表,再将其连接起来 #}
<p>{{ users | map(attribute='name') | join(', ') }}</p>
内置过滤器: tojson配合js使用,注意这里要避免HTML自动转义,所以加上safe过滤器
<script type="text/javascript">
var users = {{ users | tojson | safe }};
console.log(users[0].name);
</script>
自定义过滤器: 自定义过滤器其实就是一个函数,自己写即可
def mylen(arg):#实现一个可以求长度的函数
return len(arg)
# 该函数实现给定一个区间返回区间的内容
def interval(test_str, start, end):#过滤器中传递多个参数,第一个参数为被过滤的内容,第二第三个参数需要自己传入
return test_str[int(start):int(end)]
env = app.jinja_env
env.filters['mylen'] = mylen #注册自定义过滤器
env.filters['interval'] = interval #注册自定义过滤器
@app.route("/")
def index():
test_str = "hello"
return render_template("index.html", test_str=test_str)
#--------------------------------------------------------------------
jinja2模板
<body>
<h1>len: {{test_str|mylen}}</h1>
<h1>interval: {{test_str|interval(0,2)}}</h1> #test_str作为参数传到interval函数里
</body>
Flask 应用实例
◆URL传递参数◆
from flask import Flask,render_template,request
app = Flask(__name__)
@app.route("/post/<id>") #参数需要放在"<>"中,并且要与函数中传入的参数同名
def post(id): #加入参数,函数名称要与上面的路由名称相同
return "请求的参数是 %s" %id
@app.route("/user=<name> password=<pasd>") #可同时传递多个参数
def post1(name,pasd):
return "用户名: %s 密码: %s" %(name,pasd)
if __name__ == '__main__':
app.run(host="0.0.0.0",port="80",debug=True)
◆URL反向解析◆
反转url主要用于模版和页面的重定向(从视图函数到url的转换)
from flask import Flask,render_template,request
from flask import url_for
app = Flask(__name__)
@app.route("/")
def index():
print(url_for("post",id="lyshark"))
return "/"
@app.route("/post/<id>")
def post(id):
return "<h1> hello %s </h1>" %id
if __name__ == '__main__':
app.run(host="0.0.0.0",port="80",debug=True)
◆URL地址跳转◆
url跳转(重定向)及url反转功能应用
from flask import Flask,render_template,request
from flask import url_for,redirect
app = Flask(__name__)
@app.route("/")
def index():
return "<b> 这是首页 </b>"
@app.route("/quest/<is_login>")
def quest(is_login):
if is_login == "1":
return "<b> 登陆成功...</b>" #1为登陆成功,其他为失败,失败则跳转到登陆函数(下面的login)
else:
return redirect(url_for("login")) #失败,跳转到登陆函数(界面)
@app.route("/login/")
def login():
return "<b> 请登陆... </b>"
if __name__ == '__main__':
app.run(host="0.0.0.0",port="80",debug=True)
◆静态文件引入◆
<link rel="stylesheet" href="{{ url_for('static',filename='css/index.css') }}"> // 加载、static目录下的css目录下的index.css文件
<script src="{{ url_for('static',filename='js/index.js') }}"></script> // 加载js文件
<img src="{{ url_for('static',filename='images/aa.jpg') }}"> // 加载后台图片
<a href="{{ url_for('login') }}">登陆</a> // 点击登陆从index跳转到login页面
◆简单的参数传递◆
HTML index.html
<body>
<p>第一个flask页面</p>
<p>姓名:{{ username }}</p>
<p>height:{{ height }}</p>
</body>
后台 app.py
from flask import Flask,url_for,redirect,render_template
app = Flask(__name__)
@app.route("/")
def index():
info = {
"username":"lyshark",
"gender":"man",
"height":"165"
}
#如果有多个参数,可以将所有的参数放到字典中,然后以**kwargs的方式传递进去,info为上面定义的字典
#这里直接写模版文件名称,如果在模版文件在temlate/html目录下,则这里需要写'html/index.html'
return render_template("index.html",**info)
#渲染模版,传参数,如果参数较少,可以直接写关键字参数及值,如下:
#return render_template('index.html',username='name',gender="man",height="178")
if __name__ == '__main__':
app.run(host="0.0.0.0",port="80",debug=True)
◆复杂的参数传递◆
HTML index.html
<body>
<p>第一个flask页面</p>
<p>姓名:{{ username }}</p>
<p>height:{{ height }}</p>
<hr>
<p>{{ person.name }}---{{ person.age }}</p> //此处对应上面py中定义的Person类
<p>{{ city.bj }}</p> //第一种取值方式
<p>{{ city['tj'] }}</p> //第二种取值方式
</body>
后台 app.py
from flask import Flask,url_for,redirect,render_template
app = Flask(__name__)
@app.route('/')
def index():
class Person(object):
name='tttt'
age=18
p = Person()
info = {
'username' :'name',
'gender':"man",
'height' : "178",
'person':p,
'city':{
'bj':"bj",
'tj':'tj'
}
}
return render_template('index.html',**info)
#return render_template('index.html',username='name',gender="man",height="178")
if __name__ == '__main__':
app.run(debug=True)
◆自定义错误页◆
@app.errorhandler(404)
def page_noe_found(error):
return render_template('home/404.html'),404
@app.errorhandler(500)
def page_noe_found(error):
return render_template('home/500.html'),500
◆IF语句的使用◆
HTML: index.html
<body>
{% if users and users.age >10 %} #这里的users为py文件里传递的user字典,users.age为py文件user字典里的age
<a href="#">{{ users.aa }}</a>
<a href="#">{{ users.bbb}}</a>
{% else %}
<a href="#">登陆</a>
<a href="#">注册</a>
{% endif %}
</body>
后台: app.py
from flask import Flask,url_for,redirect,render_template
app = Flask(__name__)
@app.route('/<is_login>')
def index(is_login):
if is_login == "1": #模拟1为登陆成功
user = {
"aa":"test",
'bbb':'注销',
'age':"11"
}
return render_template('index.html',users=user)
else:
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
◆FOR语句的使用◆
HTML: index.html
<body>
{% for k,v in user.items() %} #for语句
<p>{{ k }}----{{ v }}</p>
{% endfor %}
</body>
后台: app.py
from flask import Flask,url_for,redirect,render_template
app = Flask(__name__)
@app.route('/')
def index():
users = {
'username':'tsdf',
'age':11
}
return render_template('index.html',user=users)
if __name__ == '__main__':
app.run(debug=True)
◆钩子函数的使用◆
before_request函数,就是一个装饰器,他可以把需要设置为钩子函数的代码放到视图函数执行之前执行.
from flask import Flask,url_for,redirect,render_template,request
app = Flask(__name__)
@app.route('/')
def index():
print ('index')
return 'index'
@app.before_request
def mybefore_request():
print ('before_request')
if __name__ == '__main__':
app.run(debug=True)
Flask 实战例子
◆实现登陆验证◆
HTML: index.html
<body>
<form action="/" method="post">
<input type="text" placeholder="用户名" name="username" />
<input type="password" placeholder="密码" name="password" />
<input type="submit" value="发送"/>
</form>
<div>
<p>用户名: {{ user }}</p>
<p>密码: {{ pasd }}</p>
</div>
</body>
后台: app.py
from flask import Flask,render_template,request
app = Flask(__name__)
@app.route("/",methods=['POST','GET'])
def index():
if request.method == "POST":
username = request.form.get("username")
password =request.form.get("password")
print("收到用户名: %s --->收到密码: %s" %(username,password))
return render_template("index.html",user=username,pasd=password) #可以指定返回的数据
elif request.method == "GET":
return render_template("index.html")
if __name__ == '__main__':
app.run()
◆实现文件上传◆
HTML: upload.html
<body>
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file">
<input type="submit" value="上传文件">
</form>
<p style="color: green"> 上传状态: {{ file_flage }}</p>
</body>
后台: app.py
from flask import Flask,render_template,request
app = Flask(__name__)
@app.route("/upload",methods=['POST','GET'])
def upload():
if request.method == "GET":
return render_template("upload.html")
elif request.method == "POST":
files = request.files["file"] #获取到返回文件的名称
print("上传文件详细名称: %s" %files)
print("上传文件简略名称: %s" %files.filename)
files.save(files.filename) #上传文件到当前目录,这里可以做更多判断
return render_template("upload.html",file_flage="上传文件完成...")
if __name__ == '__main__':
app.run()
◆实现Cookie◆
from flask import Flask,render_template,request
from flask import make_response
app = Flask(__name__)
@app.route("/set")
def set_cookie():
cook = make_response("设置cookie完成...")
cook.set_cookie("Name","lyshark",max_age=3600)
return cook
@app.route("/get")
def get_cookie():
cook = request.cookies.get("Name")
return "cookie 设置用户=%s" %cook
@app.route('/del')
def del_cookie():
cook=make_response("删除cookie完成...")
cook.delete_cookie('Name')
return cook
if __name__ == '__main__':
app.run()
◆实现Session◆
from flask import Flask,render_template,request
from flask import session,url_for,escape,redirect
import os
app = Flask(__name__)
@app.route('/')
def index(): #自动验证session
if 'username' in session:
return '用户 %s 已经登陆成功...' % escape(session['username'])
return '您还没有登陆呢...'
@app.route('/login', methods=['GET', 'POST'])
def login(): #登陆session
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form action="" method="post">
<p><input type=text name=username>
<p><input type=submit value=登陆>
</form>
'''
@app.route('/get')
def get(): #获取session
return "用户: %s" %session.get('username')
@app.route('/logout')
def logout(): #注销session
session.pop('username', None)
# session.clear() #清空session里的所有数据
return redirect(url_for('index'))
app.secret_key = os.urandom(24) #加盐,服务端每次重启都会变化
if __name__ == '__main__':
app.run()
◆表格结构遍历◆
HTML index.html
<body>
<table border="1">
<thead>
<th>书名</th>
<th>作者</th>
<th>价格</th>
</thead>
<tbody>
{% for book in temp %}
<tr>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
后台: app.py
from flask import Flask,render_template,request
app = Flask(__name__)
@app.route('/')
def index():
book = [
{'name':'西游记','author':'吴承恩','price':111},
{'name': '红楼梦', 'author': '曹雪芹', 'price': 121},
{'name': '水浒传', 'author': '施耐庵', 'price': 131},
{'name': '三国演义', 'author': '罗贯中', 'price': 141}
]
return render_template('index.html',temp=book)
if __name__ == '__main__':
app.run()
◆表格属性增强◆
HTML index.html
<body>
<form action="/" method="post">
<input type="text" placeholder="用户名" name="username" />
<input type="password" placeholder="密码" name="password" />
<input type="submit" value="发送"/>
</form>
<table border="1">
<thead>
<th>用户名</th>
<th>密码</th>
</thead>
<tbody>
{% for temp in user %}
<tr>
<td>{{ temp.user }}</td>
<td>{{ temp.pass }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
后台: app.py
from flask import Flask,render_template,request
app = Flask(__name__)
temp = [
{"user":"admin","pass":"1233"},
{"user":"lyshark","pass":"qwer"},
]
@app.route("/",methods=['POST','GET'])
def index():
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
data = {"user":username,"pass":password} #组合数据
temp.append(data) #追加数据到列表
return render_template("index.html",user=temp)
elif request.method == "GET":
return render_template("index.html",user=temp)
if __name__ == '__main__':
app.run()
原文地址:https://www.cnblogs.com/LyShark/p/11136289.html