简体   繁体   中英

Accessing class instances in multiple flask views?

Let's say I have a class which stores important, dynamic data which I need to render my sites. This class should be created individually per user, and the data from the class needs to get updated according to some user input, so I have at least two views:

@app.route('/')
def index():
    myclass = MyClass()
    return render_template('index.html')

@app.route('/_update', methods=['GET'])
def update():
    ret_data = {"value": request.args.get('c', type=float)}
    a = myclass.calculate(ret_data['value'])
    return jsonify(result=a)

Ofcourse it can't work this way, because myclass wouldn't exist in update() - so a working solution would be to make myclass global on creation. But this doesn't seem clean and it ruins the possibility for individual classes per session.

So, is there any clean way to access a class instance in different views, or how should I handle this, it doesn't feel like an uncommon scenario to me.

Secondly, I would like to have the class instance created for every user, but also closed when every a user closes his browser window etc. - I don't really get how to do this, I have a __del__() function in my class, but it won't be used if I set the instance to global.

Thank you very much!

You have a fundamental misunderstanding about how web applications work. They are stateless : nothing is shared between requests for any particular user. On the contrary, any global variable will be accessible to whichever user happens to hit the application next.

The way to store state for a user is to put it in the database. You can use a session cookie to associate an individual user with their particular data.

As Daniel Rosemann pointed out, it's probably not how one should design a web application. There is however a way to reach that functionality using global variables plus multiple instances. I don't know enough about python to estimate how wrong (or even dangerous) the use of global variables is, but it seems working for me - I'm happy about every comment on this solution:

Setting two global dicts, one to store the class instances, one for keep track if the instance is still relevant:

global session_instances, session_alive
session_instances = {}
session_alive = {}

In my root view I create a uuid and save the class instance with it in the dict and start a thread which should close my class after some time:

@app.route('/')
def index():
    if not session.get('uid'):
        session['uid'] = uuid.uuid4()
        session_instances.update({session['uid'] : pyd2d.d2d()})
        session_alive.update({session['uid'] : 0})
        t = Thread(target=close_session, args = (session['uid'], ))
        t.start()
    return render_template('index.html')

The thread responsible for closing (eg 15 seconds after the last request):

def close_session(uid):
    global session_alive
    while True:
        time.sleep(15)
        if session_alive[uid] == 0:
            session_instances[uid].stop()
            break
        session_alive[uid] = 0

And finally, to update the timer anytime a request is send:

@app.before_request
def before_request():
    global session_alive
    if session.get('uid'):
        session_alive[session['uid']] = 1

This seems to work just fine. Should I feel bad about using global variables, or is it ok in cases like this? I appreciate any input!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM