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

前言:css

      - 爲何我要使用 flask-socketio模塊,而不是flask-sockets?html

      - 由於flask-socketio與前端流行的websocket庫socketio語法相似,先後端交互容易理解,而且flask-socketio能很是容易得與flask項目結合。前端

效果預覽:python

    後端數字更改,自動推送到前端jquery

1.安裝 flask-socketioweb

pip install flask-socketio

2.項目結構sql

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__.pyjson

# 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.pyflask

# 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>

 4. 項目啓動

在項目目錄下,執行:

python manage.py runserver

或者與gunicorn、uWSGI等結合使用。

相關文章
相關標籤/搜索