2

I'm creating a game on Flask and want to have a counter across the entire session. I put together some psuedo code for the general outline of the project. Basically it's a script that pulls a random question from a database, collects user input, returns the correct answer, and then starts over again at the user input route. I want to add a counter that will appears regardless of the function of route. I looked into Flask sessions, but it was confusing where or how to implement... any thoughts/ suggestions? Sessions or otherwise?

get_db_info():
    connects to a database

@app.route('/questions')
def user_input():
    collects user input and puts into variable

@app.route('/answers')
def results():
    if user input = results:
        print(correct!)
    elif:
        print(incorrect)
    renders back to user_input()
mk2080
  • 872
  • 1
  • 8
  • 21

1 Answers1

2

You already mention sessions, I think they are the solution to your problem:

Flask-Session is an extension for Flask that adds support for Server-side Session to your application.

Here is an example of doing this with a session. It stores three counters, one for total accesses to the app and two for accesses to individual routes. If you call /A three times and then /B, it will give you

accessed B 1 times, accessed app 4 times

from flask import Flask, session
from flask_session import Session

app = Flask(__name__)
# Check Configuration section for more details
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
Session(app)

@app.route('/')
def reset():
    session["counterA"]=0
    session["counterB"]=0
    session["counterTotal"]=0

    return "all counters were reset"

@app.route('/A')
def routeA():
    if not "counterA" in session:
        session["counterA"]=0

    if not "counterTotal" in session:
        session["counterTotal"]=0

    session["counterA"]+=1
    session["counterTotal"]+=1

    return "accessed A {} times, accessed app {} times".format(session["counterA"], session["counterTotal"])
@app.route('/B')
def routeB():
    if not "counterB" in session:
        session["counterB"] = 0

    if not "counterTotal" in session:
        session["counterTotal"] = 0

    session["counterB"] += 1
    session["counterTotal"] += 1

    return "accessed B {} times, accessed app {} times".format(session["counterB"], session["counterTotal"])


if __name__ == '__main__':
    app.run()

The session behaves like a dictionary and is available across all routes. You can simply put your counter there.

For the sake of completeness, a solution without sessions is also possible: In principle, the flask routes behave just like python functions. So the following will work:

counter = 0
@app.route('/questions')
def user_input():
    global counter
    print(counter)
    counter+=1

@app.route('/answers')
def results():
    global counter
    print(counter)
    counter+=1

I would discourage the use of globals, they can make your code very hard to read and are not thread safe.

lhk
  • 27,458
  • 30
  • 122
  • 201
  • Thank you, this is very helpful. I'm trying to incorporate the first solution into my code and need some clarification. Would I just put counter+=1 in the answers route under an if statement? I guess I was hoping for an example of how to increment the counter within another route as well. Do I need to state counter in session or something like that? – mk2080 Nov 04 '18 at 23:14
  • You have to add the "counter" to session. Somewhere in your code you need to initialize it: session["counter"]=0. If you try to read the value session["counter"] before this initialization, it will raise an error. That's why I have the if statement. The first time this route is called, the counter is added to session, after that you can just read it. Once the counter is added, you can do counter["session"]+=1. The session is shared across routes, so you can increment it everywhere and it is persistent. – lhk Nov 05 '18 at 09:49
  • @MadelineKinnaird I updated my answer with a detailed demo – lhk Nov 05 '18 at 10:09