1. 程式人生 > >結合manage.py,在flask項目中使用 flask-socketio

結合manage.py,在flask項目中使用 flask-socketio

serve containe mod viewport comm gen 顯示 使用 消息

1.安裝 flask-socketio

pip install flask-socketio

2.項目結構

myproject/
|-- env/
    |-- <python虛擬環境>
|-- report/ <項目的模塊名稱>
|-- api_1/ <接口藍圖>
|-- __init__.py
|-- views.py |-- main/ <前端藍圖> |-- __init__.py |-- views.py <路由和視圖函數文件> ----------------------------------> 要增加websocket相關代碼 |-- forms.py <表單類文件, wtforms插件必須項> |-- templates <HTML模板> |-- static <靜態文件夾>
|-- index.html <前端頁面> ------------------------------------> 要增加websocket相關代碼 |-- XXXXXX/ <其它藍圖> |-- __init__.py ----------------------------------------------------> 要增加websocket相關代碼 |-- models.py <數據庫模型文件> |-- migrations/ <數據庫表關系文件夾,Flask-Migrate遷移數據庫時使用> |-- config.py <項目的配置文件> |-- manage.py <用於啟動程序以及其它程序任務> --------------------------------> 要增加websocket相關代碼

3.修改代碼

1) 修改 myproject/report/__init__.py

# encoding: utf-8

from flask import Flask
from flask_mail import Mail
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
from config import config
from flask_restful import Api
from flask_cors import CORS     # 解決跨域請求
from
flask_jwt_extended import JWTManager from flask_socketio import SocketIO # 新添加的代碼 mail = Mail() moment = Moment() db = SQLAlchemy() api = Api() async_mode = None # 新添加的代碼 socketio = SocketIO() # 新添加的代碼 from report.api_1.views import ServiceCheckApi, GetRecordData# 為了避免循環引用問題,在這裏導入 # 初始化app def app_create(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) config[config_name].init_app(app) mail.init_app(app) moment.init_app(app) db.init_app(app) jwt = JWTManager(app) # 路由和其他處理程序定義 # 註冊藍圖 from .main import main as main_blueprint # 從當前目錄下面的main子目錄中導入main對象 app.register_blueprint(main_blueprint) api.add_resource(ServiceCheckApi, /api/service_check) # api與websocket無關 api.add_resource(GetRecordData, /api/get_data) # add_resource 函數使用指定的endpoint 將路由註冊到框架上 api.init_app(app) # api初始化必須放在路由註冊之後 CORS(app) # 跨域請求 socketio.init_app(app=app, async_mode=async_mode) # 新添加的代碼 return app

2) 修改 myproject/manage.py

# encoding: utf-8
import os
from flask_script import Manager
from report import app_create
from flask_migrate import Migrate, MigrateCommand
from report import db, socketio  # 新添加代碼


app = app_create(os.getenv(FLASK_CONFIG) or default)  # 設置啟動方式,可選:development、testing、production
manager = Manager(app)
migrate = Migrate(app, db)  # 使用Migrate將app與db關聯


# 自定義命令 ,
# 在命令行使用: python manage.py runserver
# @manager.command
# def runserver():
#     print(‘running‘)


# 添加額外二級命令
# 第一種方式:自定義命令
# manager.add_command(‘db‘,DBmanager)  # ‘db‘是自定義的命令名字
# 在命令行使用: python manage.py db init  ,init是自定義的函數


# 第二種方式:數據遷移使用MigrateCommand中自帶的命令(常用)
# 該模塊中帶有的命令的使用順序(順序不能亂):
# python manage.py db init
# python manage.py db migrate
# python manage.py db upgrade
manager.add_command(db, MigrateCommand)
manager.add_command(run, socketio.run(app=app, host=0.0.0.0, port=5000)) # 新加入的代碼,重寫manager的run命令


if __name__ == __main__:
    manager.run()

3)修改 myproject/report/main/views.py

# encoding: utf-8

import re
import requests
from . import main
from flask import render_template,redirect, url_forfrom report import socketio
import time
from flask_socketio import emit # 新加入的代碼
from threading import Lock
import random

# 新加入的代碼-開始
thread = None
thread_lock = Lock()

def background_thread(users_to_json):
    """Example of how to send server generated events to clients."""
    while True:
        print(users_to_json)
        users_to_json = [{‘name‘: ‘王騰‘ + str(random.randint(1, 100))}]
        socketio.sleep(0.5) # 每五秒發送一次
        socketio.emit(‘user_response‘, {‘data‘: users_to_json}, namespace=‘/websocket/user_refresh‘)

@socketio.on(‘connect‘, namespace=‘/websocket/user_refresh‘)
def connect():
    """ 服務端自動發送通信請求 """
    global thread
    user_to_json = ‘‘
    with thread_lock:
        if thread is None:
            thread = socketio.start_background_task(background_thread, (users_to_json, ))
    emit(‘server_response‘, {‘data‘: ‘試圖連接客戶端!‘})


@socketio.on(‘connect_event‘, namespace=‘/websocket/user_refresh‘)
def refresh_message(message):
    """ 服務端接受客戶端發送的通信請求 """
    emit(‘server_response‘, {‘data‘: message[‘data‘]})
# 新加入的代碼-結束

@main.route(/, methods=[GET])
def index():
    return render_template(index.html)

4)修改myproject/report/main/templats/index.html

需要註意到是:

server_response、
user_response、
connect、
connect_event 

這幾個自定義事件在前後端的對應關系。emit是發送消息,on是接收消息

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title>xxx</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 引入css文件  start-->
        <link href="https://cdn.bootcss.com/bootstrap/4.1.0/css/bootstrap.css" rel="stylesheet">
        <!-- 引入css文件  end-->
    </head>
    <body style="margin: 0 auto">
        <div class="container">
            <div class="row">
                <div style="margin-bottom: 5%" class="col-md-12 text-center head-title-font">
                    <button id="auto_num" class="btn btn-primary" style="width: 10%"></button>
                </div>
            </div>
        </div>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.slim.js"></script>
<!-- 新添加代碼  start -->
    <script src="https://cdn.bootcss.com/socket.io/2.1.1/socket.io.dev.js"></script>
    <script>
        var socket = io(http://127.0.0.1:5000/websocket/user_refresh);-------------------------->  後臺接口
        socket.on(connect, function() { // 發送到服務器的通信內容
        socket.emit(connect_event, {data: 我已連接上服務端!});
    });

    socket.on(server_response, function(msg) {
        //顯示接受到的通信內容,包括服務器端直接發送的內容和反饋給客戶端的內容
        console.log(msg);
    });
    socket.on(user_response, function(msg) {
        // 獲取後端傳過來的業務數據
        var obj = eval(msg.data[0]);
        console.log(obj);
        $("#auto_num").empty();
        $("#auto_num").append(obj[name]);

    });
    </script>
<!-- 新添加代碼 end -->
    </body>
</html>

結合manage.py,在flask項目中使用 flask-socketio