flask与http
# Request
# flask get
from flask import Flask
from flask import request
app = Flask(__name__)
## 1. 匹配 /hello
@app.route("/hello")
def hello_1():
return 'hello flask'
## 2. 匹配 /hello/<params>
@app.route("/hello/<username>")
def hello_2(username):
print('username:%s' % username)
return 'hello ' + username
## 3. 匹配 /hello/args/<params>?id=xx&&age=xx
@app.route("/hello/args/<username>")
def hello_3(username):
print('username:%s' % username)
id = request.args.get("id")
age = request.args.get("age")
return 'hello, id from request %s, age from request %s' % (id, age)
if __name__ == '__main__':
app.run()
@app.route("/hello/<username>")
, 匹配/hello/<params>
/hello/args/<params>?id=xx&&age=xx
,id = request.args.get("id")
取出参数id
# flask post
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/form', methods=['post'])
def post_1():
return 'post test'
## form
## application/x-www-form-urlencoded or multipart/form-data
@app.route('/form2', methods=['post'])
def post_2():
username = request.form['username']
password = request.form['password']
return 'post received username:%s, password: %s' % (username, password)
## json
@app.route('/form4', methods=['post'])
def post_4():
username = request.json['username']
password = request.json['password']
return 'post received username:%s, password: %s' % (username, password)
if __name__ == '__main__':
app.run()
username = request.json['username']
, 相当于request.get_json()['username']
,当post
提交的是json
类型的数据username = request.form['username']
, 相当于request.get_json()['username']
,当post
提交的是表单类型的数据
# 请求钩子
掘金 flask 请求钩子 (opens new window)
Flask 常用请求钩子如下:
before_first_request
:在处理第一个请求之前运行before_request
:在每次请求之前运行,如果没有未处理的异常抛出,会在每个请求结束后运行after_request
:如果没有未处理的异常抛出,在每次请求结束后运行teardown_request
:即使有未处理的异常抛出,也会在每个请求结束后运行
# Response
完整地说,视图函数可以返回最多由三个元素组成的元组:响应主体、状态码、首部字段。
其中首部字段可以为字典,或是两元素元组组成的列表。
# 只包含主体
@app.route('/hello')
def hello():
...
return '<h1>Hello, Flask!</h1>'
# 默认的状态码为200,下面指定了不同的状态码:
@app.route('/hello')
def hello():
...
return '<h1>Hello, Flask!</h1>', 201
# 有时你会想附加或修改某个首部字段。
# 比如,要生成状态码为3XX的重定向响应,需要将首部中的Location字段设置为重定向的目标URL:
@app.route('/hello')
def hello():
...
return '', 302, {'Location': 'http://www.example.com'}
# 重定向
from flask import Flask, redirect
# ...
@app.route('/hello')
def hello():
return redirect('http://www.example.com')
# redirect, 重定向 路由 '/hello'
@app.route('/hi')
def hi():
return redirect(url_for('hello'))
# 错误响应
# 404
from flask import Flask, abort
...
@app.route('/404')
def not_found():
abort(404)
# 响应格式
from flask import Flask, make_response, request, redirect, url_for, abort, session, jsonify
# 测试如下 /note/xml 请求 xml /note/json 请求 json
@app.route('/note', defaults={'content_type': 'text'})
@app.route('/note/<content_type>')
def note(content_type):
content_type = content_type.lower()
# text
if content_type == 'text':
body = '''Note
to: Peter
from: Jane
heading: Reminder
body: Don't forget the party!
'''
response = make_response(body)
response.mimetype = 'text/plain'
# html
elif content_type == 'html':
body = '''<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>Note</h1>
<p>to: Peter</p>
<p>from: Jane</p>
<p>heading: Reminder</p>
<p>body: <strong>Don't forget the party!</strong></p>
</body>
</html>
'''
response = make_response(body)
response.mimetype = 'text/html'
# xml
elif content_type == 'xml':
body = '''<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Peter</to>
<from>Jane</from>
<heading>Reminder</heading>
<body>Don't forget the party!</body>
</note>
'''
response = make_response(body)
response.mimetype = 'application/xml'
# json
elif content_type == 'json':
body = {"note": {
"to": "Peter",
"from": "Jane",
"heading": "Remider",
"body": "Don't forget the party!"
}
}
response = jsonify(body)
# equal to:
# response = make_response(json.dumps(body))
# response.mimetype = "application/json"
else:
abort(400)
return response
- 根据不同请求参数生成
body
, 比如json
就生成json
对象,xml
,html
同理 make_response(body)
生成响应对象response.mimetype = 'application/xml'
,响应对象的mimetype
属性设置MIME
类型
# 设置 cookie
from flask import Flask, make_response
...
@app.route('/set/<name>')
def set_cookie(name):
response = make_response(redirect(url_for('hello')))
response.set_cookie('name', name)
return response
response = make_response(redirect(url_for('hello')))
生成响应对象- 响应对象设置
cookie
,response.set_cookie('name', name)
# 设置 session
import os
from flask import redirect, session, url_for, request,
# 更安全的做法是把密钥写进系统环境变量(在命令行中使用export或set命令),或是保存在.env文件中
# 获取密钥
app.secret_key = os.getenv('SECRET_KEY', 'secret string')
# 模拟用户登入
@app.route('/login')
def login():
session['logged_in'] = True # 写入session
return redirect(url_for('hello'))
@app.route('/')
@app.route('/hello')
def hello():
name = request.args.get('name')
if name is None:
name = request.cookies.get('name', 'Human')
response = '<h1>Hello, %s!</h1>' % name
# 根据用户认证状态返回不同的内容
if 'logged_in' in session:
response += '[Authenticated]'
else:
response += '[Not Authenticated]'
return response
# ajax
# AJAX
from jinja2.utils import generate_lorem_ipsum
@app.route('/post')
def show_post():
post_body = generate_lorem_ipsum(n=2)
return '''
<h1>A very long post</h1>
<div class="body">%s</div>
<button id="load">Load More</button>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function() {
$('#load').click(function() {
$.ajax({
url: '/more',
type: 'get',
success: function(data){
$('.body').append(data);
}
})
})
})
</script>''' % post_body
@app.route('/more')
def load_post():
return generate_lorem_ipsum(n=1)
$.ajax()
, 请求/more
接口/more
接口 返回 html
# 服务端推送
- 传统轮询
- 长轮询
SSE
websocket