ブループリントを活用するために再構築した Flask アプリがあります。アプリケーションが実行され、SocketIO と私の socketio.on イベントを除いて、すべてがうまくいっているようです。SocketIO と Web ソケットが Chrome デバッガーで接続または切断しようとしているのを見たことがありません。ここでFlask SocketIO チャットの例を確認し、いくつかのアイデアを得ました。すべてのイベントを views.py に戻しました。sockio.on イベントが呼び出されない、または起動しない理由がわかりません。これが私のコードです。app.py
from factory import create_app
from flask.ext.socketio import SocketIO
app = create_app()
socketio = SocketIO(app)
factory.py
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask
# from flask.ext.socketio import SocketIO
from flask.ext.login import LoginManager
import os
from celery import Celery
lm = LoginManager()
# socketio = SocketIO()
lm.login_view = 'main.login'
lm.session_protection = 'strong'
def create_app():
app = Flask(__name__)
app.clients = {}
app.config.from_object(os.environ.get('APP_CONFIG')) # export APP_CONFIG=settings.Development
lm.init_app(app)
from project.main import main as main_blueprint
app.register_blueprint(main_blueprint)
# socketio.init_app(app)
# print app.config['LOGPATH']
if not os.path.isdir(app.config['LOGPATH']):
print 'Log dir not found'
os.makedirs(app.config['LOGPATH'])
if not os.path.isdir(app.config['UPLOAD_FOLDER']):
print 'Upload dir not found'
os.makedirs(app.config['UPLOAD_FOLDER'])
# See Flask error handling for more info on logging
file_handler = RotatingFileHandler(app.config['LOGPATH'] + 'my.log', maxBytes=1024 * 1024 * 10, backupCount=20)
file_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s -%(module)s - %(lineno)d - %(message)s"))
app.logger.setLevel(logging.DEBUG)
app.logger.addHandler(file_handler)
app.logger.debug('Starting My Application')
# app.logger.debug(socketio)
return app
def make_celery(app=None):
app = app or create_app()
celery = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL'])
# celery.conf.update(app.config)
celery.config_from_envvar('APP_CONFIG')
TaskBase = celery.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery.Task = ContextTask
return celery
メイン/ _init_.py
from flask import Blueprint
main = Blueprint('main', __name__, template_folder='templates', static_folder='static')
import views
# import events
main/views.py
from celery import chain
from flask import render_template, request, url_for, jsonify, current_app, session
from . import main
from flask.ext.socketio import emit, disconnect
from ..app import socketio
from flask.json import dumps
from werkzeug.utils import secure_filename, redirect
from flask.ext.login import login_required, login_user, logout_user
from uuid import uuid4
from project.tasks import *
@main.route('/')
# @login_required
def index():
event_count = 0
current_app.logger.debug('Loaded homepage')
current_app.logger.debug(socketio)
return render_template('index.html',
event_count=event_count,
http_id=session['http_id'])
# @login_required
@main.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
websocket_session_id = request.form.get('session')
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
chain(
parse.s(filename, session['http_id']),
create_sphere.s(session['http_id'], websocket_session_id, url_for('main.event', _external=True))
)()
# parse.delay(filename, session['http_id'])
# (filename, session['http_id']),
# link=create_sphere.s(session['http_id'], websocket_session_id, url_for('main.event', _external=True))
# )
# parse.apply_async(chain)
return jsonify({'status': 'processing CSV'})
else:
return jsonify({'status': 'wrong file type'})
if request.method == 'GET':
return render_template('upload.html')
@main.route('/clients', methods=['GET'])
def clients():
return jsonify({'clients': current_app.clients.keys()})
@main.route('/event/', methods=['POST'])
def event():
print '\n'
print 'request =', request
print 'request.json =', request.json
current_app.logger.debug('task: {t}'.format(t=request.json['task']))
current_app.logger.debug('success: {s}'.format(s=request.json['success']))
websocket_id = request.json['websocket_id']
current_app.logger.debug(websocket_id)
if request.json['task'] == 'task_sphere' and request.json['success']:
current_app.logger.debug('successfully parsed CSV data')
current_app.logger.debug(request)
websocket_id = request.json['websocket_id']
http_id = request.json['http_id']
current_app.logger.debug(websocket_id)
current_app.logger.debug(http_id)
# try:
conn = pymongo.MongoClient(current_app.config['MONGO_URL'])
db = conn.events
collection = db['%s' % http_id]
current_app.logger.debug('Collection: {c}'.format(c=collection))
ns = current_app.clients.get(websocket_id)
if ns:
current_app.logger.debug(ns)
nodes = dumps(list(collection.find({'type' : 'node'})))
edges = dumps(list(collection.find({'type' : 'edge'})))
if nodes:
ns.emit('insert_nodes', nodes)
if edges:
ns.emit('insert_edges', edges)
# ns.emit('insert_data', dumps(list(collection.find())))
# return 'ok'
# except:
# print 'Could not connect to MongoDB: %s'
# return 'ok'
return 'ok'
# @lm.user_loader
# def load_user(username):
# u = main.config['USERS_COLLECTION'].find_one({"_id": username})
# if not u:
# return None
# return User(u['_id'])
@main.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'admin':
error = 'Invalid Creds'
else:
session['logged_in'] = True
session['http_id'] = str(uuid4())
return redirect(url_for('main.login'))
return render_template('login.html', error=error)
@main.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('main.login'))
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in current_app.config['ALLOWED_EXTENSIONS']
##### Put events here for the time being #####
@socketio.on('status', namespace='/events')
def events_message(message):
current_app.logger.debug(message['status'])
print 'socketio.on: status'
emit('status', {'status': message['status']})
@socketio.on('disconnect request', namespace='/events')
def disconnect_request():
print 'socketio.on: disconnect request'
current_app.logger.debug('DISCONNECT REQUEST')
emit('status', {'status': 'Disconnected!'})
disconnect()
@socketio.on('connect', namespace='/events')
def events_connect():
print 'socketio.on: connect'
websocket_id = str(uuid4())
session['websocket_id'] = websocket_id
current_app.logger.debug(websocket_id)
current_app.clients[websocket_id] = request.namespace
emit('websocket_id', {'websocket_id': websocket_id})
@socketio.on('disconnect', namespace='/events')
def events_disconnect():
print 'socketio.on: diconnect'
current_app.logger.debug('DISCONNECT')
del current_app.clients[session['websocket_id']]
print('Client %s disconnected' % session['websocket_id'])
static/js/application.js
var namespace = '/events'; // change to an empty string to use the global namespace
var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
var jared;
var edges;
var nodes;
socket.on('connect', function () {
console.log('socketio: connect');
});
socket.on('disconnect', function () {
console.log('socketio: disconnect');
$('#websocket_id').text('not available');
});
socket.on('websocket_id', function (msg) {
console.log('updating html elements with correct session', msg.websocket_id);
$('input[name="session"]').val(msg.websocket_id);
$('#websocket_id').text(msg.websocket_id);
});
socket.on('insert_nodes', function (msg) {
//console.log(msg);
//jared = msg;
$('#myModal').modal('hide');
nodes = JSON.parse(msg);
console.log('here are the nodes', nodes);
var pcGeometry = new THREE.Geometry();
for (var i = 0; i < nodes.length; i++) {
var position = nodes[i].position;
//console.log(position);
vector = new THREE.Vector3(position.x, position.y, position.z);
//console.log(vector);
pcGeometry.vertices.push(vector);
}
//console.log(geometry);
pcMat = new THREE.PointCloudMaterial();
pcMat.size = 10;
pcMat.transparent = true;
pcMat.blending = THREE.AdditiveBlending;
pcMat.color = new THREE.Color(0x5555ff);
pc = new THREE.PointCloud(pcGeometry, pcMat);
pc.sizeAttenuation = true;
webGLScene.add(pc);
});
socket.on('insert_edges', function (msg) {
function getById(id, myArray) {
return myArray.filter(function (obj) {
if (obj._id.$oid == id) {
return obj
}
})[0]
}
edges = JSON.parse(msg);
console.log('here are the edges', edges);
var material = new THREE.LineBasicMaterial({
opacity: .3,
blending: THREE.AdditiveBlending,
transparent: true
});
//geometry.vertices.push(start);
for (var i = 0; i < edges.length; i++) {
var start = edges[i].start.$oid;
var start_pos = getById(start, nodes);
var start_vec = new THREE.Vector3(start_pos.position.x, start_pos.position.y, start_pos.position.z);
var end = edges[i].end.$oid;
var end_pos = getById(end, nodes);
var end_vec = new THREE.Vector3(end_pos.position.x, end_pos.position.y, end_pos.position.z);
var geometry = new THREE.Geometry();
geometry.vertices.push(start_vec);
geometry.vertices.push(end_vec);
var line = new THREE.Line(geometry, material);
webGLScene.add(line);
}
});
socket.on('status', function (msg) {
console.log('status', msg);
});