Flask
目录1 flask 简介
-
Django:
- Django适合大型项目
- 功能组件齐全
- 加载项多,相应更加消耗资源
-
Flask
- 更加适合小型项目,api等环境
- 第三方组件非常全
- 运行稳定性相对较差
-
Flask依赖
-
Flask:Flask库文件
-
Jinja2:模板渲染库
-
MarkupSafe:返回安全标签,只要Fask返回模板或者标签时都会依赖MarkupSafe
-
werkzeug 德文"工具”== uWSGI:底层是 WSGI Flask项目启动都是基于werkzeug
-
-
启动Flask
# 三行启动Flask,提供服务 from flask import Flask app = Flask(__name__) app.run()
2 Flask
2.1 Flask response
from flask import Flask
app = Flask(__name__) # __name__ 表示的是录有项目所在目录名,可自定义,保证唯一即可
@app.route('/') # 为 Flask 应用对象增加路由
def hello_world(): # 与路由绑定的视图函数 视图函数名尽可能保持唯一
return 'Hello World!' # 相当于 Django 中的 HttpResponse
@app.route('/tem')
def tem():
return render_template('tem.html') # 模板存放路径 templates(默认)
@app.route('/red')
def red():
return redirect('/tem')
# Response header中加入: Location: /tem
@app.route('/getfile')
def getfile():
return send_file('1.jpg') # 返回文件
# 打开并返回文件内容,自动识别文件类型Response header中加入:Content-Type: 可以被客户端识别的文件类型
# 不能识别的文件会下载处理
@app.route('/getjson')
def getjson():
d = {
'user': 'admin',
'passwd': '123456',
}
return jsonify(d) # 返回标准格式的JSON字符串
# return d 时,本质上在执行jsonify(d)
if __name__ == '__main__':
app.run() # 启动Flask 应用
2.2 Flask Request
import os.path
from flask import Flask, render_template, request, redirect
app = Flask(__name__)
FLASK_DEBUG = 1
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
# get 请求url 如下: http://localhost:5000/login?id=1
print(request.url) # 完整url
print(request.url_root) # 请求host
print(request.url_rule) # 请求路由
print(request.url_charset) # url编码方式
print(request.values.to_dict()) # 接收所有请求数据并输出为字典
print(request.args.get('id')) # 获取URL中的指定参数的数据
return render_template('login.html')
elif request.method == 'POST':
print(request.url) # 完整url
# 在Flask 获取FormData request.form
print(request.form) # ImmutableMultiDict([('username', 'admin'), ('password', '')])
print(request.form.get('username')) # admin
print(request.form.to_dict()) # {'username': 'admin', 'password': ''}
# 获取一个 FileStorage Flask文件特殊对象
print(request.files.get('file')) # <FileStorage: 'black_main.png' ('image/png')>
file = request.files.get('file')
save_file = os.path.join('imgs', file.filename)
file.save(save_file)
# 获取其他数据
print('request.headers: ', request.headers)
print('request.cookies: ', request.cookies)
print('request.path: ', request.path) # /login
print('request.host: ', request.host) # localhost:5000
print('request.host_url: ', request.host_url) # http://localhost:5000/
# 特殊提交方式数据获取
# 获取Content-Type:application/json时提交的数据
# print('request.json: ', request.json)
# Content-Type 无法被识别,可获取原始请求体中的数据
# print('request.data', request.data)
return render_template('tem.html')
if __name__ == '__main__':
app.run()
2.3 Flask 中的 Session
from flask import Flask, render_template, request, session, redirect
app = Flask(__name__)
app.secret_key = "!@#QEWasdZXC" # 添加key,必填
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
if request.form.get("username") == "admin":
session["user"] = request.form.get("username") # 开启session
# 序列化session字典为字符串
# 使用secret_key加密字符串
return redirect('/')
else:
return render_template('login.html')
@app.route('/')
def index():
print(session.get('user'))
print(request.cookies)
# 从cookie中获取'session'的值
# 通过secret_key解密session
# 反序列化成字典
if session.get('user') == 'admin':
return render_template('tem.html')
else:
return redirect('/login')
if __name__ == '__main__':
app.run()
2.4 Flask 模板语言
2.4.1 Jinja2
-
{{}}
引用变量数据,执行函数 -
{%%}
逻辑代码 -
实例
from flask import Flask, render_template STUDENT = {'name': 'dog', 'age': 33, 'gender': '中'} STUDENT_LIST = [ {'name': 'dog', 'age': 1, 'gender': '中'}, {'name': 'very', 'age': 2, 'gender': '男'}, {'name': 'good', 'age': 3, 'gender': '女'} ] STUDENT_DICT = { 1: {'name': 'dog', 'age': 4, 'gender': '中'}, 2: {'name': 'very', 'age': 5, 'gender': '男'}, 3: {'name': 'good', 'age': 6, 'gender': '女'}, } app = Flask(__name__) app.debug = True # 当@app.template_global()有修饰foo()时,可直接在模板中引用,注意此时引用的是foo()名称 @app.template_global() def foo(x, y): return x + y # 当@app.template_global()没有修饰foo()时,需要在return中指定引用的foo() @app.route("/stu") def stu(): return render_template("stuinfo.html", funfoo=foo, stu_info=STUDENT, stu_list=STUDENT_LIST, stu_dict=STUDENT_DICT) if __name__ == '__main__': app.run("0.0.0.0", 5000)
-
html模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>stuinfo</title> </head> <body> {{ stu_info }} <table border="1px"> <tr> <td>name</td> <td>age</td> <td>gender</td> </tr> <tr> <td>{{ stu_info.name }}</td> <td>{{ stu_info.get('age') }}</td> <td>{{ stu_info['gender'] }}</td> </tr> </table> {{ stu_list }} <table border="1px"> {% for stu in stu_list %} <tr> <td>{{ stu.get('name') }}</td> <td>{{ stu['age'] }}</td> <td> {% if stu.gender != '男' and stu.gender != '女' %} 性别错误 {% else %} {{ stu.gender }} {% endif %} </td> </tr> {% endfor %} </table> {{ stu_dict }} <table> {% for stu in stu_dict %} <tr> <td>{{ stu_dict[stu].name }}</td> <td>{{ stu_dict[stu].get('age') }}</td> <td>{{ stu_dict[stu]['gender'] }}</td> </tr> {% endfor %} </table> <table> {% for stu,item in stu_dict.items() %} <tr> <td>{{ stu }}</td> <td>{{ item.name }}</td> <td>{{ item['age'] }}</td> <td>{{ item.get('gender') }}</td> </tr> {% endfor %} </table> <!--# 当@app.template_global()没有修饰foo()时,需要在return中指定引用的foo()--> <p>funfoo: {{ funfoo(1,3) }}</p> <!--当@app.template_global()有修饰foo()时,可直接在模板中引用,注意此时引用的是foo()名称--> <p>foo: {{ foo(2,3) }}</p> {% macro my_input(type,name) %} <input type="{{ type }}" name="{{ name }}"> {% endmacro %} <p>在html中函数创建的input标签: 用户名:{{ my_input('text','username') }} 密码:{{ my_input('password','password') }}</p> </body> </html>
2.5 Flask 路由
-
endpoint
不能重复,对应视图函数,默认是视图函数名 -
通常用作 反向查询URL地址(viewfunction-->endpoint-->URL)。例如,在flask中有个视图,你想把它关联到另一个视图上(或从站点的一处连接到另一处)。不用去千辛万苦的写它对应的URL地址,直接使用
URL_for()
就可以from flask import Flask, render_template app = Flask(__name__) app.debug = True def warp(fun): # 定义一个装饰器 def inner(*args, **kwargs): print('request校验') ret = fun(*args, **kwargs) print('request校验完成') return ret return inner # 装饰器所装饰的是从装饰器开始从上到下第一个函数。 @app.route('/login', methods=['GET', 'POST']) @warp # 装饰器的本质是调用被装饰的函数,经过修改后,再返回当前函数。因此自定义的视图装饰器需要放在@app.route之下。 def login(): return render_template('login.html') @app.route('/index', methods=['GET', 'POST'], endpoint='index') @warp # 当装饰器同时装饰两个视图函数时,会引发endpoint重复错误,可通过在路由中指定名称来规避。 # AssertionError: View function mapping is overwriting an existing endpoint function: inner def index(): print(url_for(endpoint='index')) return 'Hello World!' if __name__ == '__main__': app.run()
-
methods
:设置当前路由允许请求的方式 -
redirect_to
:308 PERMANENT REDIRECT
,没有进入视图直接跳转 -
strict_slashes
:默认为True,即严格要求 -
动态参数路由:
/<int:page>
import os.path
from flask import Flask, render_template, send_file
app = Flask(__name__)
app.debug = False
@app.route('/home', redirect_to='/', strict_slashes=False, )
def home():
return render_template('home.html')
@app.route('/<int:page>', defaults={'key': 'fcarey'})
def index(page, key):
return f'Hello world!\n\t{key}\npage{page}'
@app.route('/media/<folder>/<filename>')
def media(folder, filename):
file_path = os.path.join(folder, filename)
# 限定访问目录
# file_path = os.path.join('imgs', filename)
print(file_path)
return send_file(file_path)
if __name__ == '__main__':
app.run()
2.6 Flask 初始化实例化参数
template_folder
:模板存放路径static_folder
:定义静态文件存放路径static_url_path
:静态文件访问路径 默认值为/{static_folder}
static_host
:静态文件访问服务HOST
from flask import Flask, render_template
# 修改默认的模板存放路径、静态文件存放路径及静态文件访问路径
app = Flask(__name__, template_folder='temp', static_folder='imgs', static_url_path='/imgs')
app.debug = False
@app.route('/')
def home():
return render_template('media.html')
if __name__ == '__main__':
app.run()
media.html
文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>media</title>
</head>
<body>
<img src="/imgs/1.jpg" alt="img">
</body>
</html>
2.7 Flask setting
-
app.default_config
:定位到默认配置 -
DEBUG
模式:编辑代码时自动重启服务,Log打印级别最低
错误信息透传 -
TESTING
模式:无限接近生产环境,编辑代码不会自动重启,Log级别较高,错误信息不再透传 -
SESSION_COOKIE_NAME
:存放在浏览器cookie中session的名称,注意:第一个字符,不能是空格app.config["SESSION_COOKIE_NAME"] = "it is not Session"
-
创建Flask配置文件:
setting.py class DebugConfig: DEBUG = True SECRET_KEY = "%^&*(%^&*" PERMANENT_SESSION_LIFETIME = 3600 SESSION_COOKIE_NAME = "it is Not Session" class TestConfig: TESTING = True SECRET_KEY = "sessionkey" PERMANENT_SESSION_LIFETIME = 30 SESSION_COOKIE_NAME = "TestConfig"
-
引入配置文件
from flask import Flask, render_template from setting import DebugConfig, TestConfig app = Flask(__name__) app.config.from_object(TestConfig) @app.route('/') def home(): return 'hello world!' if __name__ == '__main__': app.run()
2.8 Flask BluePrint
-
BluePrint
:功能隔离、路由隔离# app01.py from flask import Blueprint app01 = Blueprint(name='app01', import_name=__name__, url_prefix="/admin") @app01.route('/') def index(): return "page from app01" # app02.py from flask import Blueprint app02 = Blueprint(name='app02', import_name=__name__, url_prefix="/") @app02.route('/') def index(): return "page from app02" # Controler.py from flask import Flask from app01.app01 import app01 from app02.app02 import app02 app = Flask(__name__) app.register_blueprint(blueprint=app01) app.register_blueprint(blueprint=app02) if __name__ == '__main__': app.run()
2.8.1 使用Flask模拟Django
- 实现运行
manage.py
就可以启动flask
# 目录结构
.
|---manage.py
|---app01
|---__init__.py
|---app01.py
# app01.py
from flask import Blueprint
manage = Blueprint(name='admin', import_name=__name__, url_prefix='/admin')
@manage.route('/login')
def login():
return 'bp from manager!'
# __init__.py
from flask import Flask
from app01.app01 import manage
def create_app():
app = Flask(__name__)
app.debug = True
app.register_blueprint(blueprint=manage)
return app
# manage.py
from app01 import create_app
app = create_app()
if __name__ == '__main__':
app.run()
2.9.2 Flask-session模块使用
# 目录结构
.
|---manage.py
|---app01
|---__init__.py
|---app01.py
# app01.py
from flask import Blueprint, session
manage = Blueprint(name='admin', import_name=__name__, url_prefix='/admin')
@manage.route('/login')
def login():
session['key'] = 'value'
print(session)
return 'bp from manager!'
# __init__.py
from app01.app01 import manage
from flask import Flask
from flask_session import Session
from redis import Redis
def create_app():
app = Flask(__name__)
app.debug = True
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = Redis('192.168.50.118', 6379)
Session(app=app)
app.register_blueprint(blueprint=manage)
return app
# manage.py
from app01 import create_app
app = create_app()
if __name__ == '__main__':
app.run()
2.9 Flask 特殊装饰器
@app.before_request
:请求进入视图函数之前@app.after_request
:请求结束,返回影响客户端之前- 匹配顺序:bf1>bf2>bf3>view func>af1>af2>af3
- 若bf2异常:bf1>bf2>af1>af2>af3
- 注:此时af1,af2,af3在脚本中为反序
@app.errorhandler
:重定义错误信息
from flask import Flask, render_template, request, session, redirect
app = Flask(__name__)
app.secret_key = "!@#QEWasdZXC"
@app.before_request
def bf1():
print('bf1')
if session.get('user') == 'admin':
return '123'
else:
return None
@app.before_request
def bf2():
print('bf2')
@app.before_request
def bf3():
print('bf3')
@app.after_request
def af3(res):
print("af3")
return res
@app.after_request
def af2(res):
print("af2")
return res
@app.after_request
def af1(res):
print("af1")
return res
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
if request.form.get("username") == "admin":
session["user"] = request.form.get("username")
return redirect('/')
else:
return render_template('login.html')
@app.route('/')
def index():
if session.get('user') == 'admin':
return render_template('tem.html')
else:
return redirect('/login')
@app.errorhandler(404)
def error(ErrorMessage):
print(ErrorMessage)
return '无此页面'
if __name__ == '__main__':
app.run()
3 Flask 与 MongoDB
from flask import Flask, request, render_template, redirect
from pymongo import MongoClient
app = Flask(__name__)
app.debug = True
mongo_client = MongoClient('127.0.0.1', 27017)
db = mongo_client['flask']
@app.route('/reg', methods=['get', 'post'])
def req():
if request.method == 'GET':
return render_template('reg.html')
else:
user_info = {
'username': request.form['username'],
'password': request.form['password'],
}
db.members.insert_one(user_info)
return redirect('/login')
@app.route('/login', methods=['get', 'post'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
user_info = request.form.to_dict()
if db.members.find_one({'username': user_info['username']})['password'] == request.form.get('password'):
return 'login ok!'
else:
return redirect('/login')
if __name__ == '__main__':
app.run()
4 Flask WebSocket
4.1 flask环境准备
pip3 install --upgrade Flask-SocketIO==4.3.1
pip3 install --upgrade python-engineio==3.13.2
pip3 install --upgrade python-socketio==4.6.0
pip3 install --upgrade flask==1.1.4
pip3 install --upgrade Werkzeug==1.0.1
pip3 install --upgrade itsdangerous==1.1.0
pip3 install --upgrade Jinja2==2.11.2
pip3 install --upgrade MarkupSafe==2.0.1
4.2 WebSocket 前期信息准备
4.2.1 打印服务端所接收的WSGI环境变量
# 通过websock访问接收到的environment,其明显特征如下:
'HTTP_SEC_WEBSOCKET_VERSION': '13',
'HTTP_SEC_WEBSOCKET_EXTENSIONS': 'permessage-deflate',
'HTTP_SEC_WEBSOCKET_KEY': 'MPP5twOyN0G5K1cbIbDDTQ==',
'HTTP_CONNECTION': 'keep-alive, Upgrade',
'HTTP_COOKIE': 'session=2d04a6a0-76b4-4c03-b6e3-e08ce82c7517; io=c0157a090983456a9dbe95839366ae03',
'HTTP_SEC_FETCH_DEST': 'websocket',
'HTTP_SEC_FETCH_MODE': 'websocket',
'HTTP_SEC_FETCH_SITE': 'same-origin',
'HTTP_PRAGMA': 'no-cache',
'HTTP_CACHE_CONTROL': 'no-cache',
'HTTP_UPGRADE': 'websocket',
'wsgi.input': <_io.BufferedReader name=792>,
'wsgi.input_terminated': False,
'wsgi.websocket_version': '13',
'wsgi.websocket': <geventwebsocket.websocket.WebSocket object at 0x00000172D99622C0>,
wsgi.websocket
:就是websocket
4.2.2 readyState表示状态
var ws = new WebSocket('ws://127.0.0.1:5000/ws');
ws
WebSocket { url: "ws://127.0.0.1:5000/ws", readyState: 1, bufferedAmount: 0, onopen: null, one rror: null, onclose: null, extensions: "", protocol: "", onmessage: null, binaryType: "blob" }
readyState: 0
:连接中readyState: 1
:已建立连接readyState: 2
:客户端关闭连接readyState: 3
:服务端关闭连接
4.2.3 接收消息位置
message { target: WebSocket, isTrusted: true, data: "hello, it is server!", origin: "ws://localhost:5000", lastEventId: "", ports: Restricted, srcElement: WebSocket, currentTarget: WebSocket, eventPhase: 2, bubbles: false, … }
- 接收消息返回的是字典类型,所要接收的信息位于
data
字段中
4.3 建立websocket会话
4.3.1 客户端到服务端单播
from geventwebsocket.handler import WebSocketHandler
from geventwebsocket.server import WSGIServer
from geventwebsocket.websocket import WebSocket # 语法提示
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route("/ws")
def ws():
sock = request.environ.get('wsgi.websocket') # type:WebSocket
print(sock)
while True:
msg = sock.receive()
print(msg)
send_msg = 'hello, it is server!'
sock.send(send_msg)
if __name__ == '__main__':
# app.run() # flask原生WSGI不支持websocket
http_server = WSGIServer(("127.0.0.1", 5000), app, handler_class=WebSocketHandler) # environment
http_server.serve_forever()
<head>
<title>WebSocket Test</title>
</head>
<body>
<h1>WebSocket Test</h1>
<script>
var ws = new WebSocket("ws://localhost:5000/ws");
// onopen回调函数,当WebSocket连接建立完成时,执行
ws.onopen = function () {
ws.send('hello, it is client!');
console.log("WebSocket connected");
};
// onmessage回调函数,当WebSocket接收到消息时,执行
ws.onmessage = function (message) {
console.log(message.data);
};
ws.onclose = function () {
console.log("WebSocket disconnected");
};
</script>
</body>
</html>
- 浏览器调试窗口console标签下:
ws.send('hello')
4.3.2 群聊
from geventwebsocket.handler import WebSocketHandler
from geventwebsocket.server import WSGIServer
from geventwebsocket.websocket import WebSocket # 语法提示
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
sock_list = []
@app.route("/ws")
def ws():
sock = request.environ.get('wsgi.websocket') # type:WebSocket
sock_list.append(sock)
while True:
try:
msg = sock.receive()
"""解决当收到消息为空时"""
if msg is None:
continue
else:
print(msg)
except:
"""解决刷新页面时,之前已创建的websocket会话关闭产生的错误"""
sock_list.remove(sock)
break
"""解决自己发送消息,自己还会收到的问题"""
for s in sock_list:
if s == sock:
continue
else:
send_msg = f'server has received: {msg}'
s.send(send_msg)
return 'ok'
if __name__ == '__main__':
# app.run() # flask原生WSGI不支持websocket
http_server = WSGIServer(("127.0.0.1", 5000), app, handler_class=WebSocketHandler) # environment
http_server.serve_forever()
<head>
<title>WebSocket Test</title>
</head>
<body>
<h1>WebSocket Test</h1>
<p>
<input type="text" id="send_msg">
<button id="send">发送</button>
</p>
<body id="ws_msg"></body>
<script>
var ws = new WebSocket("ws://localhost:5000/ws");
document.getElementById('send').addEventListener('click',function () {
var send_msg = document.getElementById('send_msg').value;
ws.send(send_msg);
});
// onopen回调函数,当WebSocket连接建立完成时,执行
ws.onopen = function () {
ws.send('hello, it is client!');
console.log("WebSocket connected");
};
// onmessage回调函数,当WebSocket接收到消息时,执行
ws.onmessage = function (message) {
var p = document.createElement('p');
p.innerText= message.data;
document.getElementById('ws_msg').appendChild(p);
};
ws.onclose = function () {
console.log("WebSocket disconnected");
};
</script>
</body>
</html>
4.3.3 单播
import json
from geventwebsocket.handler import WebSocketHandler
from geventwebsocket.server import WSGIServer
from geventwebsocket.websocket import WebSocket # 语法提示
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('p2p.html')
sock_list = {}
@app.route("/ws/<username>")
def ws(username):
"""不是WS协议上来的请求为None,WS协议认证失败也为None"""
sock = request.environ.get('wsgi.websocket', None) # type:WebSocket
if not sock:
return '请使用WS协议连接'
while True:
try:
sock_list[username] = sock # 将用户名与sock作映射关系
"""获取json序列化后的数据"""
msg = sock.receive()
msg_dict = json.loads(msg) # 反序列化数据为字典
target_user = msg_dict.get('target_user') # 取出数据中的目标用户,以获取对应的sock
recv_sock = sock_list.get(target_user)
recv_sock.send(msg)
except:
"""解决刷新页面时,之前已创建的websocket会话关闭产生的错误"""
break
return 'ok'
if __name__ == '__main__':
http_server = WSGIServer(("0.0.0.0", 80), app, handler_class=WebSocketHandler) # environment
http_server.serve_forever()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>单播</title>
</head>
<body>
<p><input type="text" name="username" id="username" placeholder="请输入你的名字">
<button type="submit" id="login">进入聊天室</button>
</p>
<p>给<input type="text" name="target_user" id="target_user">发送<input type="text" name="msg" id="msg">
<button type="submit" id="send">发送</button>
</p>
<div id="content_text"></div>
</body>
<script type="application/javascript">
var ws = null; // 申明全局变量ws,使其可以接收并发送数据
document.getElementById('login').addEventListener('click', function () {
var username = document.getElementById('username').value;
ws = new WebSocket('ws://192.168.50.117/ws/' + username);
// 1.发送 GET 请求 到 http://192.168.50.117/ws/username
// 2.等待http://192.168.50.117/ws/username的响应
// 3.接收并响应 Accept 校验是否通过,此时状态为 101 不断开请求
// 4.验证通过,创建Socket连接到socket服务 (后台的wsgi.websocket监听中)
// --4.验证失败,101 断开连接
// 5.开始使用(websocket协议加密方式的)Socket通讯
ws.onopen = function () {
console.log('欢迎:' + username);
};
// 接收数据
ws.onmessage = function (message) {
console.log(message)
var msg = JSON.parse(message.data);
var tag_p = document.createElement('p');
tag_p.innerText = msg.username + ":" + msg.send_msg;
document.getElementById('content_text').appendChild(tag_p);
};
});
// 发送数据
document.getElementById('send').addEventListener('click', function () {
var username = document.getElementById('username').value;
var target_user = document.getElementById('target_user').value;
var send_msg = document.getElementById('msg').value;
var msg = {
'username': username,
'target_user': target_user,
'send_msg': send_msg,
}
ws.send(JSON.stringify(msg))
console.log(msg)
});
</script>
</html>
5 Flask 与 HTML5
- 实现注册与登陆,注册时上传拍照图片,登陆时加载图片。
HBuilder X
- HTML5+ API Reference (html5plus.org)
from flask import Flask, request, jsonify, send_file
from pymongo import MongoClient
app = Flask(__name__)
app.debug = True
MC = MongoClient(host='127.0.0.1', port=27017)
db = MC['fcarey01']
@app.route('/upload', methods=['post'])
def upload():
user_info = request.form.to_dict()
file = request.files.get('jpg')
file.save(user_info.get('username') + '.jpg')
user_info['avatar'] = user_info.get('username') + '.jpg'
res = db.members.insert_one(user_info)
if res.inserted_id:
return f"恭喜{user_info.get('username')}用户,注册成功!"
else:
return 'out'
@app.route('/login', methods=['post'])
def login():
user_info = request.form.to_dict()
user = db.members.find_one(user_info)
print(user)
if user:
user['_id'] = str(user.get('_id')) # 将ObjectId转换为字符串
return jsonify({"code": 0, "msg": "登录成功", "data": user})
else:
return jsonify({"code": 1, "msg": "登录失败"})
@app.route('/get_avatar/<filename>')
def get_avatar(filename):
return send_file(filename)
if __name__ == '__main__':
app.run(host='192.168.50.117', port=5000)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
<h1 class="mui-title">phone page</h1>
</header>
<div class="mui-content">
<form class="mui-input-group">
<div class="mui-input-row">
<label>用户名:</label>
<input type="text" class="mui-input-clear" id='username' value="user01">
</div>
<div class="mui-input-row">
<label>密码:</label>
<input type="password" class="mui-input-clear" id='password' value="1234">
</div>
<div class="mui-input-row">
<label>男:</label>
<input name='gender' type="radio" value="1" checked>
</div>
<div class="mui-input-row">
<label>女:</label>
<input name='gender' type="radio" value="2">
</div>
<button type="button" class="mui-btn mui-btn-red mui-btn-block" id='cmr-btn'>开始拍照</button>
</form>
<form class="mui-input-group">
<div class="mui-input-row">
<label>用户名:</label>
<input type="text" class="mui-input-clear" id='user' value="user01">
</div>
<div class="mui-input-row">
<label>密码:</label>
<input type="password" class="mui-input-clear" id='passwd' value="1234">
</div>
<div class="mui-input-row">
<button type="button" class="mui-btn mui-btn-green mui-btn-block" id='submit'>登录</button>
</div>
</form>
<div class="mui-input-row" style="text-align: center;">
<img id="cmr-pic" style="width: 150px; height: 150px; border-radius: 50%;">
</div>
</div>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 扩展API加载完毕后调用onPlusReady回调函数
document.addEventListener( "plusready", onPlusReady, false );
// 扩展API加载完毕,现在可以正常调用扩展API
function onPlusReady() {
console.log("plusready");
};
mui.init();
mui.back = function(){};
// 拍照
document.getElementById('cmr-btn').addEventListener('tap',function () {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var gender_list = document.getElementsByName('gender');
mui.toast('开启摄像头');
var cmr = plus.camera.getCamera();
var res = cmr.supportedImageResolutions[30];
var fmt = cmr.supportedImageFormats[0];
console.log("Resolution: "+res+", Format: "+fmt);
cmr.captureImage( function( path ){
mui.toast( "Capture image success: " + path );
// console.log(path);
var task = plus.uploader.createUpload( "http://192.168.50.117:5000/upload",
{ method:"POST",priority:100 },
function ( t, status ) {
// 上传完成
if ( status == 200 ) {
alert( "Upload success: " + t.url );
} else {
alert( "Upload failed: " + status );
}
}
);
task.addFile( path, {key:"jpg"} );
task.addData( "username", username );
task.addData( "password", password );
for (var i = 0; i<gender_list.length; i++) {
if (gender_list[i].checked) {
var gender = gender_list[i].value;
}
}
task.addData( "gender", gender );
//task.addEventListener( "statechanged", onStateChanged, false );
task.start();
},
function( error ) {
mui.toast( "Capture image failed: " + error.message );
},
// options
{
filename:'_doc/fcarey/a.jpg',
resolution:res,
format:fmt,
},
);
});
document.getElementById('submit').addEventListener('tap',function () {
var user = document.getElementById('user').value;
var passwd = document.getElementById('passwd').value;
mui.post(
'http://192.168.50.117:5000/login',{
'username':user,
'password':passwd,
},function(data){
console.log(JSON.stringify(data.data.avatar));
document.getElementById("cmr-pic").src = 'http://192.168.50.117:5000/get_avatar/'+data.data.avatar;
alert(data.msg);
},'json'
);
});
</script>
</body>
</html>
标签:__,return,name,Flask,app,request,学习
From: https://www.cnblogs.com/f-carey/p/17300283.html