首页 > 其他分享 >Flask 学习

Flask 学习

时间:2023-04-09 14:22:11浏览次数:44  
标签:__ return name Flask app request 学习

Flask

目录

1 flask 简介

  1. Django:

    1. Django适合大型项目
    2. 功能组件齐全
    3. 加载项多,相应更加消耗资源
  2. Flask

    1. 更加适合小型项目,api等环境
    2. 第三方组件非常全
    3. 运行稳定性相对较差
  3. Flask依赖

    1. Flask:Flask库文件

    2. Jinja2:模板渲染库

    3. MarkupSafe:返回安全标签,只要Fask返回模板或者标签时都会依赖MarkupSafe

    4. werkzeug 德文"工具”== uWSGI:底层是 WSGI Flask项目启动都是基于werkzeug

  4. 启动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_to308 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

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

相关文章

  • flask---day04()
    上节回顾#1蓝图 -第一步:导入-第二步:实例化得到对象,可以指定static和templates-第三步:app中注册蓝图,注册蓝图时,可以指定前缀-第四步:使用蓝图,注册路由,注册请求扩展#2g对象 -当次请求的全局对象,在当次请求中可以放值和取值-跟session的区......
  • Markdown的学习笔记
    Markdown学习笔记1、Markdown的字体字体粗体斜体斜体加粗删除线2、Markdown的引用引用选择xxx走向人生巅峰3、Markdown的分割线分割线4、Markdown的图片插入图片插入图片 4、Markdown的超链接超链接点击跳转到tly的博客5、Markdown的列表列表列表1......
  • Khan公开课 - 统计学学习笔记:(二)总本、样本、集中趋势、离中趋势
    三、统计学&集中趋势统计学statistics是对数据的descriptive,而不是将所有数据呈现,根据统计,可以进行inferential(推理),对未来的判断。集中趋势CentralTendency,求中间值就是average,通常指的是mean(算术平均),但是广义上也包括median、和mode。计算的方式不同,不能说哪种方法好,看具体情况......
  • Android学习笔记(五十):声明、请求和检查许可
    基于安全需求,应用对Android系统提供的contentprovider或者service的访问需要在安装时进行许可,这就是AndroidManifest.xml文件中的permission中声称,之前已经很多例子。同样如果其他应用要访问我们的数据,我们也可以要求这些应用必须获得用户授权方可访问我们的数据。申请授权:请求per......
  • Java for Web学习笔记(二六):JSTL(2)Core Tag(上)
    可以在JSP中替代Java代码的几乎所有功能,包括条件编程,循环,迭代和内容输出。taglib的directive如下:<%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%><c:out>AttributesNameRequiredRequest-timeTypeDescriptionvaluetruetruejava.lang.StringExpression......
  • Java for Web学习笔记(三):Servlet(1)Maven
    什么是Maven在http://maven.apache.org/中对Mavent进行介绍,可以:一、发布project信息二、管理Jar包三、提供uniformbuildsystem,使用POM(projectobjectmodel)如果我们使用Eclipse是最新的Mars版本,Maven已经集成进来,所以不需要进行额外的配置,当然,如果我们需要自行安装一个特定位......
  • Pro Android学习笔记(九):了解Content Provider(下下)
    Contentprovider作为信息的读出,比较常见的还有文件的读写,最基础的就是二进制文件的的读写,例如img文件,音频文件的读写。在数据库中存放了该文件的路径,我们可以通过ContentProvider获得InputSream和OutputStream,实现对文件的操作。ProAndroid4.0提及有关内容,但语焉不详,可同时参考h......
  • Pro Android学习笔记(八):了解Content Provider(下中)
    在之前提供了小例子BookProvider,我们回过头看看如何将通过该ContentProvider进行数据的读取。(1)增加privatevoidaddBook(Stringname,Stringisbn,Stringauthor){/*从ContentProvider的insert()方法的参数可以看到,通过ContentValues来进行数据的传递。ContentValues是k......
  • Android学习笔记(五四):通知Notification(上)
    运行在后台的Service,需要某种方式来通知用户,例如通知用户来电,通知有新的消息。这类的通知显示在statusbar上,还可以带有硬件的提醒,例如振动、LED灯闪,播放声音等等。在Android中,可以通过NotificationManager来发起一个通知。我们先看一个简单的例子,如有图所示。界面很简单,两个大butt......
  • Android学习笔记(五三):服务Service(下)- Remote Service
    之前所谈的Service属于LocalService,即Service和Client在同一进程内(即同一application内),Service的生命周期服从进程的生命周期。在实际应用上,有时希望Service作为后台服务,不仅被同一进程内的activity使用,也可被其他进程所使用,针对这种情况,需要采用bindService,也就是RemoteService......