pythonWEB框架比较
当前流行的python web 框架有Django ,Flask ,Tornado,Sanic 。
Django web:
优点:大而全,ORM models ,model Form ,admin ,csrf ,session
缺点:资源浪费
Flask web:
优点:小而精,ORM:x , Form:x , admin:x, csrf:x, session:√, 第三方组件 : 全
缺陷:因为用的是第三方组建,所以相对Django稳定性较差
Tornado:
优点:异步IO非阻塞 原生websocket
缺点:啥都没有
Sanic Web:是基于python3.5之上的一个web框架,除了与Flask功能类似之外,它还支持异步请求处理,这意味着你可以使用Python3.5 中新的异步/等待语法,使你的程序运行更加快速。
async def index():
初识Flask
启动一个flask项目
现在我们用三行代码实现一个flask工程,:
程序:只需要写一个普通python程序
运行后:程序运行如下,说明运行正常
访问地址:浏览器中输入程序运行时候返回的地址
查看服务端: 服务端有返回说明已经运行成功并可以访问.
上述程序不完美的地方在于显示404,原因是没有添加路由和返回信息,因此我们对程序进行改进
加入路由和返回信息
给程序添加路由和返回信息:
运行结果:
现在,我们的flask程序就算是完全正常了。
Flask默认开启的ip地址是:http://127.0.0.1:5000/
但在运行时可能存在无法访问的问题,特别是当我们在linux服务器上搭建flask时,此时需要将代码修改如下:
# 加入debug=True后代码修改会自动重启 # 加入host='0.0.0.0'后会监听端口的任何地址 app.run(host='0.0.0.0', port=5000, debug = True)
主要是将host地址修改为“0.0.0.0”,后面两项参数可以自行修改,运行后如下:可以用127.0.0.1或者本机局域网ip地址访问
window端访问不是“http://0.0.0.0:5000/”,而是服务器的本机局域网ip地址,在windows命令终端输入ipconfig命令即可查到本机局域网IP地址, 本人的为http://192.168.31.213:5000/
因此访问界面如下:
Flask三剑客
上面的flask项目中的返回信息我们就用到了三剑客之一,相对于Django的三剑客,flask也有三剑客,并且还有额外的两个剑客用于传送文件和json数据。
- Flask 中的HttpResponse其实就是直接返回字符串,Flask中直接return 即可。
- Flask中的redirect用于重定向,可以重定向到指定页面,它通常和url_for函数一起使用
- Flask 中的render为render_template用于返回htmls页面
三剑客示例
程序:
三剑客扩展
传送json和文件的两剑客jsonify和send_file
from flask import Flask, render_template, redirect from flask import json, jsonify, send_file app = Flask(__name__) # 告诉flask当前文件位置,通常写__name__ @app.route('/') # 添加路由 def index(): # 添加返回信息 return '这是我的第一个flask程序' # 剑客一 @app.route('/login') def login(): return render_template('login.html') # 剑客二: @app.route('/home') def home(): return redirect('/login') # 剑客三:重定向 @app.route('/json1') # 添加路由 def json1(): # 添加返回信息 Content-Type:application/json return jsonify({"name": "yal", "age": 78}) # 剑客jsonify @app.route('/json2') # 添加路由 def json2(): # 添加返回信息 Content-Type:text/html return json.dumps({"name": "yal", "age": 78}) # 对比剑客jsonify @app.route('/picture') # 添加路由 def picture(): # 添加返回信息 Content-Type:text/html return send_file('01.jpg') # 剑客send_file # 加入debug=True后代码修改会自动重启 # 加入host='0.0.0.0'后会监听端口的任何地址 app.run(host='0.0.0.0', port=5000, debug=True)
剑客jsonify运行结果:
剑客send_file运行结果:直接显示图片
send_file除了图片以外,还可以显示视频/音频等文件.
对比jsonify和json.dumps:
- json.dumps返回类型为文本 : Content-Type:text/html
- jsonify返回类型为json : Content-Type:application/json
将文件夹变为模板的操作
将文件夹变为模板之后写render_template可以直接识别到html文件.
将文件夹变为模板的操作
三剑客详细学习 >>> 点击
Flask中的request
每个框架中都有处理请求的机制(request), 但是每个框架的处理方式和机制是不同的,flask中的request用于获取前端的提交信息。
from flask import request request.method #请求方式 request.form #存储的是所有FormData中的所有数据,使用request.form.to_dict()可以转为字典输出 request.args #存储的是所有URL中的所有数据,使用request.args.to_dict()可以转为字典输出 request.json #Content-Type: application/json 存放在request.json中 request.data #当Content-Type无法被解析时,存放原始数据 request.url #请求地址 request.path #url路由地址 request.host #主机地址 request.host_url #将主机地址转换为http url request.headers #存储的是所有header信息 request.values #存储的是post提交的form和url中后的键值(例如:?id=666&net=888),一般不使用. 因为存在问题:form表单和url有同名键值时,后者会覆盖前者. request.files # 获取文件,获取后保存用request.save
Flask中的request详细学习 >>> 点击
程序示例:
@app.route('/login', methods=("GET", "POST")) def login(): if request.method == 'GET': return render_template('login.html') # 剑客二: if request.method == 'POST': print('主机地址:', request.host) print('请求地址地址:', request.url) print('url路由地址:', request.path) print('http url地址:', request.host_url) print('headers信息:', request.headers) user_info = request.form.to_dict() if user_info.get('user') == 'jj' and user_info.get('pwd') == 'pwd': return "登录成功!" return '用户名或密码错误!'
运行返回结果:
Jinja2
Flask中默认的模板语言是Jinja2,,Jinja2结合 render_template可以把后端定义的字符串传递到前端。
Jinja2模板语法
Jinja2模板语言和Django模板语言有近乎相同的语法和结构,主要掌握以下2种用法:
- 1 {{}} 引用或执行时
- 2 {%%} 逻辑代码
# Jinja2模板语言中的 for
{% for foo in g %}
{% endfor %}
# Jinja2模板语言中的 if
{% if g %}
{% elif g %}
{% else %}
{% endif %}
此外以下高级用法,了解即可:
- safe : 前端向后端传递html标签可以在前端使用 {{ tag | safe}} (Markup也可实现html标签传递)
- 模板中执行函数
- 模板复用 block
- 模块引用 include
- 模块继承 extends
- 模块宏定义后导入使用 {% import "ui/admin_page.html" as pg %}
宏定义使用实例:分页
导入跨文件夹导入:
{% import "ui/admin_page.html" as pg %}
使用:
{{ pg.page(page_data, 'admin.tag_list') }}
宏定义内容:movie2101/app/templates/ui/admin_page.html内容
{% macro page(data, url) -%}
{% if data %}
<ul class="pagination pagination-sm no-margin pull-right">
<li><a href="{{ url_for(url, page=1) }}">首页</a></li>
{% if data.has_prev %}
<li><a href="{{ url_for(url, page=data.prev_num) }}">上一页</a></li>
{% else %}
<li class="disabled"><a href="#">上一页</a></li>
{% endif %}
{% for v in data.iter_pages() %}
{% if v == data.page %}
<li class="active"><a href="#">{{ v }}</a></li>
{% else %}
<li><a href="{{ url_for(url, page=v) }}">{{ v }}</a></li>
{% endif %}
{% endfor %}
{% if data.has_next %}
<li><a href="{{ url_for(url, page=data.next_num) }}">下一页</a></li>
{% else %}
<li class="disabled"><a href="#">下一页</a></li>
{% endif %}
<li><a href="{{ url_for(url, page=data.pages) }}">尾页</a></li>
</ul>
{% endif %}
{%- endmacro %}
实例详细学习参考在FLask中利用macro实现分页组件
详细Jinja2学习 >>> 点击
程序示例:
flask.py程序:
from flask import Flask, render_template, redirect
from flask import json, jsonify, send_file
from flask import request
app = Flask(__name__) # 告诉flask当前文件位置,通常写__name__
STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'},
STUDENT_LIST = [
{'name': 'Old', 'age': 38, 'gender': '中'},
{'name': 'Boy', 'age': 73, 'gender': '男'},
{'name': 'EDU', 'age': 84, 'gender': '女'}
]
STUDENT_DICT = {
1: {'name': 'Old', 'age': 38, 'gender': '中'},
2: {'name': 'Boy', 'age': 73, 'gender': '男'},
3: {'name': 'EDU', 'age': 84, 'gender': '女'},
}
@app.route('/index') # 添加路由
def index(): # 添加返回信息
return render_template('index.html',
stu1=STUDENT,
stu2=STUDENT_LIST,
stu3=STUDENT_DICT)
# 加入debug=True后代码修改会自动重启
# 加入host='0.0.0.0'后会监听端口的任何地址
app.run(host='0.0.0.0', port=5000, debug=True)
index.html内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>index</title>
</head>
<body>
<h4>登录成功</h4>
<h5>欢迎来到flask的世界</h5>
{# ********************{{ }}用法***********************#}
{{ stu1 }}
{#************************{% %}用法***********************#}
<table border="1px">
<thead>
<tr>
<th>name</th>
<th>age</th>
<th>gender</th>
</tr>
</thead>
<tbody>
{% for stu in stu2 %}
<tr>
<td>{{ stu.name }}</td>
<td>{{ stu.get('age') }}</td>
<td>{{ stu['gender'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<table border="1px">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
<th>gender</th>
</tr>
</thead>
<tbody>
{% for id, stu in stu3.items() %}
<tr>
<td>{{ id }}</td>
<td>{{ stu.name }}</td>
<td>{{ stu.get('age') }}</td>
<td>{{ stu['gender'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
运行结果: