So, to achieve a seemless web app, not having the page reload on every new view change is pretty essential. To do this, I'm using socketio, and converting to base64 on the backend so html isn't lost in transmission.
However, when the user goes directly to the url, I want them to be able to see the same page as if a user was shown the page if they clicked the link on the index page, then loading it via socketio. (index → page)
This is the socketio routing decorator class inspired by a blog post by Ainsley Jones
class socketio_route:
def __init__(self):
self.routes = {}
def route(self, rule):
if rule[0] == '/':
rule = rule[1::]
def decorator(f):
self.routes[rule] = f
return f
return decorator
def serve(self, path):
view_func = self.routes.get(path)
if view_func:
return view_func(False)
which is then used in conjunction with the standard @app.route('/') flask decorator.
@app.route('/branches')
@skt.route('/branches')
def route_branches(fullpage=True):
values = {"data": {'branch': 'master'}}
page = render_template('default.html', **values)
if fullpage == False:
socketio.emit('page', base64.b64encode(page), namespace='/page')
else:
return render_template('index.html', socket_preload_content=page)
This returns the bare-bones page if it is accessed via socketio, and the full page (a render_template of the initial render_template) if it is accessed via the default method; directly.
I'm using flask_socketio to handle all things socketio.
Question
So, my question is, is it possible to integrate all of this into a single route decorator, or extend the existing flask @app.route() decorator?
Maybe something like this for the custom route?
@CUSTOM.route('/branches')
def branches():
values = {"data": {'branch': 'master'}}
return render_template('default.html', **values)
which would return either
socketio.emit('page', base64.b64encode(OUTPUT_FROM_ABOVE), namespace='/page')
or
render_template('index.html', socket_preload_content=OUTPUT_FROM_ABOVE)
depending on the way it was called.
I looked into flask's app.add_url_rule but was confused as to how I might integrate this into my existing socketio_route decorator class.
Can anyone suggest as to how I might go about this?
Solved
So to fix this, I did actually end up using flask's app.add_url_rule.
The socketio_route is a tad different, mainly in the fact that it directly emits a page.
class socketio_route:
def __init__(self):
self.routes = {}
def route(self, rule, f):
if rule[0] == '/':
rule = rule[1::]
self.routes[rule] = f
def serve(self, path):
view_func = self.routes.get(path)
if view_func:
socketio.emit('page', base64.b64encode(view_func(fullpage=False)), namespace='/page')
skt = socketio_route()
the custom decorator I wrote adds a route to both socketio_route and app.
def dual_route(rule):
def decorator(f):
@wraps(f)
def decorated_function(fullpage=True, *args, **kwargs):
if fullpage == False:
return f(*args, **kwargs)
else:
return render_template('index.html', socket_preload_content=f(*args, **kwargs))
app.add_url_rule(rule, decorated_function.__name__, decorated_function)
skt.route(rule, decorated_function)
return decorated_function
return decorator
and then I can just call it by:
@dual_route('/branches')
def route_branches():
values = {"data": {'branch': 'master'}}
return render_template('default.html', **values)
No comments:
Post a Comment