Closed yoyoliyang closed 3 years ago
Turbo is a Flask extension, it should be used on the application instance.
Thank you!(I bought your book
Well, I want use it in blueprint, my code was like this:
from flask import Blueprint, render_template, current_app
import sys
import threading
import time
from turbo_flask import Turbo
bp = Blueprint('cpu_load_avages', __name__, static_folder="../templates", url_prefix='/cpu')
@bp.route('/')
async def index():
return render_template('cpu.html')
@bp.context_processor
def inject_load():
load = [0,0,0]
if sys.platform.startswith('linux'):
with open('/proc/loadavg', 'rt') as f:
load = f.read().split()[0:3]
return {'load1': load[0], 'load5': load[1], 'load15': load[2]}
@bp.before_app_first_request
def before_first_request():
threading.Thread(target=update_load).start()
def update_load():
with current_app.app_context():
turbo = Turbo(current_app)
while True:
time.sleep(5)
turbo.push(turbo.replace(render_template('cpu.html'), 'load'))
but there was wrong with this:
File "/home/yang/.local/share/virtualenvs/flask_tutorial-fiBXDnIR/lib/python3.7/site-packages/flask/globals.py", line 47, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
So what should I do? I seem to use Blueprint to keep the architecture clear. Thank you very much!
You can use it anywhere in your app, including in a blueprint, but as a Flask extension it should be initialized with the Flask application instance, not with a particular blueprint.
Thank you for replay. Sorry my bad english, I think I should use app_context function to create a context environment in blueprint file, my code like this, can you help me?
app extensions.py
from turbo-flask import Turbo
turbo = Turbo
app __init__.py
from flask import Flask
from server_monitor.extensions import turbo
from server_monitor.utils import smart, ups, cpu
def create_app():
app = Flask(__name__)
app.register_blueprint(cpu.bp) # the blueprint who use turbo
# extensions
turbo.init_app(app)
return app
and cpu.py
from flask import Blueprint, render_template
import sys
import threading
import time
from server_monitor.extensions import turbo
bp = Blueprint('cpu_load_avages', __name__, static_folder="../templates", url_prefix='/cpu')
@bp.route('/')
def index():
return render_template('cpu.html')
@bp.context_processor
def inject_load():
load = [0,0,0]
if sys.platform.startswith('linux'):
with open('/proc/loadavg', 'rt') as f:
load = f.read().split()[0:3]
return {'load1': load[0], 'load5': load[1], 'load15': load[2]}
@bp.before_app_first_request
def before_first_request():
threading.Thread(target=update_load).start()
def update_load():
# how to use app_context() in there but with blueprint not Flask app
while True:
time.sleep(5)
turbo.push(turbo.replace(render_template('cpu.html'), 'load'))
from flask import current_app
# ...
def update_load():
with current_app.app_context():
while True:
time.sleep(5)
turbo.push(turbo.replace(render_template('cpu.html'), 'load'))
I got some error. My code:
from flask import Blueprint, render_template, current_app
import sys
import threading
import time
from server_monitor.extensions import turbo
bp = Blueprint('cpu_load_avages', __name__, static_folder="../templates", url_prefix='/cpu')
@bp.route('/')
def index():
return render_template('cpu.html')
@bp.context_processor
def inject_load():
load = [0,0,0]
if sys.platform.startswith('linux'):
with open('/proc/loadavg', 'rt') as f:
load = f.read().split()[0:3]
return {'load1': load[0], 'load5': load[1], 'load15': load[2]}
@bp.before_app_first_request
def before_first_request():
threading.Thread(target=update_load).start()
def update_load():
with current_app.app_context():
while True:
time.sleep(5)
turbo.push(turbo.replace(render_template('cpu.html'), 'load'))
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "/home/yang/flask_tutorial/server_monitor/utils/cpu.py", line 28, in update_load
with current_app.app_context():
File "/home/yang/.local/share/virtualenvs/flask_tutorial-fiBXDnIR/lib/python3.7/site-packages/werkzeug/local.py", line 422, in __get__
obj = instance._get_current_object()
File "/home/yang/.local/share/virtualenvs/flask_tutorial-fiBXDnIR/lib/python3.7/site-packages/werkzeug/local.py", line 544, in _get_current_object
return self.__local() # type: ignore
File "/home/yang/.local/share/virtualenvs/flask_tutorial-fiBXDnIR/lib/python3.7/site-packages/flask/globals.py", line 47, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
Oh yeah, sorry, I did not realize this was running in a thread. Do it like this:
@bp.before_app_first_request
def before_first_request():
threading.Thread(target=update_load, args=(current_app._get_current_object(),)).start()
def update_load(app):
with app.app_context():
while True:
time.sleep(5)
turbo.push(turbo.replace(render_template('cpu.html'), 'load'))
Thank you, The problem is solved. Thank you very much.
Hello, I try to relaod this topic. I know some mistakes with turbo_flask. When i use it with a simple app with no factory (create_app) in a single file , it's ok.
But with blueprints and a wsgi mode (apache) it doesn't work. So can you help me.
skeleton of my app
I follow the api's doc. I use threading with blueprint.
app.wsgi (classic not amazing)
import sys
sys.path.insert(0, '/appli/torbu')
from api import create_app
application = create_app()
init.py factory
def create_app():
app = Flask(__name__)
app.register_blueprint(bp_order) # the blueprint who use turbo
# extensions
turbo.init_app(app)
return app
order/routes.py
from flask import Blueprint, render_template, current_app
import sys
import threading
import time
from api.extensions import turbo
bp_order = Blueprint('bp_order', __name__, static_folder="../templates", url_prefix='/order')
@bp_order.route('/')
def index():
return render_template('index.html')
@bp_order.context_processor
def inject_time():
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
return {'timenow': current_time}
@bp_order.before_app_first_request
def before_first_request():
threading.Thread(target=updatetime, args=(current_app._get_current_object(),)).start()
def updatetime(app):
with app.app_context():
while True:
time.sleep(1)
turbo.push(turbo.replace(render_template('loadtime.html'), 'loadtime'))
In my log apache
ERROR in app: Exception on /turbo-stream [GET]
Traceback (most recent call last):
File "/home/emmanuel/.local/lib/python3.10/site-packages/flask/app.py", line 2528, in wsgi_app
response = self.full_dispatch_request()
File "/home/emmanuel/.local/lib/python3.10/site-packages/flask/app.py", line 1825, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/emmanuel/.local/lib/python3.10/site-packages/flask/app.py", line 1823, in full_dispatch_request
rv = self.dispatch_request()
File "/home/emmanuel/.local/lib/python3.10/site-packages/flask/app.py", line 1799, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/home/emmanuel/.local/lib/python3.10/site-packages/flask_sock/__init__.py", line 59, in websocket_route
ws = Server(request.environ, **current_app.config.get(
File "/home/emmanuel/.local/lib/python3.10/site-packages/simple_websocket/ws.py", line 319, in __init__
raise RuntimeError('Cannot obtain socket from WSGI environment.')
RuntimeError: Cannot obtain socket from WSGI environment.
Can you help me please? Someone?
Thanks.
Apache is not a supported web server for the Flask-Sock extension, which Turbo-Flask depends on.
Thanks. Do you known solution (extension) like turbo_f ? On a flask webservice, i want update different part of page.
Ok, i try with the embedded flask http (flask ... run). My page is correctly print at first load.
but my element html is not update. I insert a print(ok) during the update and it's printing.
the turbo.push line don't work (no error, nothing in page :( )
My code :
from flask import Blueprint, render_template, current_app
import sys
import threading
import time
sys.path.insert(0, '/appli/torbu')
from api.extensions import turbo
bp_order = Blueprint('bp_order', __name__, static_folder="../templates", url_prefix='/order')
@bp_order.route('/')
def index():
return render_template('index.html')
@bp_order.context_processor
def inject_time():
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
return {'loadtime': current_time}
@bp_order.before_app_first_request
def before_first_request():
threading.Thread(target=updatetime, args=(current_app._get_current_object(),)).start()
def updatetime(app):
with app.app_context():
# how to use app_context() in there but with blueprint not Flask app
while True:
time.sleep(1)
print("ok")
turbo.push(turbo.replace(render_template('loadtime.html'), 'loadtime'))
print("pass")
@EmmanuelBrache your code may or may not have problems, but as I said above, you can't use Apache with Turbo-Flask. See the docs: https://turbo-flask.readthedocs.io/en/latest/quickstart.html#deployment.
Ok but my last post is used with flask:run (localhost:5000) :) sorry
I can't really visually debug your application, sorry. Do the examples in this repository work for you? If yes, start from one of them and modify it to suit your needs.
As the title. When I use Turbo with Blueprint like this: ` bp = Blueprint(......)
bp = Turbo(bp) ` It can't work. so, what should I do?