Home > OS >  Flask can't get session var from javascript
Flask can't get session var from javascript

Time:12-05

I have a site with a dual form, first form is to select an analysis and then the rest of the form is shown.

The chosen analysis is saved as a flask session['sel_analysis']

This all works as expected.

The problem: 1: Open two tabs on the same site and select different analyses on the sites 2: The first tab still has the first analysis selected in the form and i can change values but when i submit the form the session from the second site with another analysis is loaded so the form is saved on the wrong analysis.

How did i try to solve it When a site is inFocus check if the session['sel_analysis] is the same as the selected_analysis in the form and do a location.reload() if it's not the same.

The problem with the solution: When i in javascript do a fetch on the api call (Code for the backend api call below) the session['sel_analysis'] is always None, so how can i get the session in an api call from javascript?

Python code:

app = Flask(__name__)
app.config['SECRET_KEY'] = "Very secret"
CORS(app, supports_credentials=True)

@app.route('/edit', methods=['GET', 'POST'])
def edit():
    global systems_obj_list
    sel_analysis = None
    try:
        if session["sel_analysis"]:
            for s in systems_obj_list:
                if s == session["sel_analysis"]:
                    sel_analysis = s
    except Exception as e:
        session["sel_analysis"] = None
    ...
    return render_template('edit.html', systems=systems_obj_list, selected_system=sel_system)

@app.route('/api/get-session-analysis', methods=['GET'])
def get_session_analysis():
    """Return the selected analysis from session

    Returns:
        json: Key analysis gives The name of the analysis or None if there is no session available
    """
    if request.method == 'GET':
        sys = session.get("sel_analysis")
        print(sys)
        if sys == None: sys = ""
        response = jsonify({"analysis": sys})
        response.headers.add('Access-Control-Allow-Origin', '*')
        return response

The javascript that calls the function:

async function getSessionAnalysis() {
    var analysis = await fetch('http://localhost/api/get-session-analysis', {
            method: 'GET',
            credentials: 'same-origin'
    }).then((response) => {
            j = response.json();
            console.log(j);
            return j;
        }).then((myJson) => {
            var s = myJson['analysis'];
            console.log(s);
            return s;
        });
    console.log(analysis);
    return analysis
}

The HTML for the code that runs the fetch:

{% if selected_system != None %}
    <script>
        // Check if the site is focused again and if it is check if another analysis is chosen in the same session and reload the site if it is
        console.log($('#p_sel_sys').text().replace("Currently selected analysis:  ", ""));
        var sessionAnalysis = getSessionAnalysis();
        console.log(sessionAnalysis);
        window.onfocus = function () {
            if ("{{ selected_system }} " != sessionAnalysis) {
                console.log("reload");
                // location.reload();
            }
        }
    </script>

The variable selected_system is a variable passed from backend on return on the site to get the chosen analysis in the first form, i want to check if this is the same as the session since then i can never have 2 tabs open with different analyses chosen to accidently overwriting one with another.

Like i said in python i print the session['sel_analysis'] it's always None and i don't know why?

TO CLARIFY: The cookie seems to work since i can close the tab and open a new tab and the cookie is loaded, it's just with the fetch it returns None, not if i close the tab and open it again. I can also just refresh the tab with the old chosen analysis then it will change to the latest chosen (This is what i want to do but only if the chosen analysis is not the one in the session)

CodePudding user response:

I finally fixed this! I had to change some things, i had to add session.modified = True to get the session to show the new one when it was modified, then i had to change the javascript to run the check inside the await fetch('http://localhost/api/get-session-analysis', {}).then((response) => {}).then((myJson) => {<here>}); i also had to add a . in the url after localhost for the 'same-origin' in the fetch to work properly.

These changes means some changes to the code so i'll paste the working code below.

This is the code that works:

Python:

app = Flask(__name__)
app.config['SECRET_KEY'] = "Very secret"
CORS(app, supports_credentials=True)

@app.route('/edit', methods=['GET', 'POST'])
def edit():
    global systems_obj_list
    sel_analysis = None
    try:
        if session["sel_analysis"]:
            for s in systems_obj_list:
                if s == session["sel_analysis"]:
                    sel_analysis = s
    except Exception as e:
        session["sel_analysis"] = None
    ...
    session["sel_analysis"] = "name"
    session.modified = True
    return render_template('edit.html', systems=systems_obj_list, selected_system=sel_analysis)

@app.route('/api/get-session-analysis', methods=['GET'])
def get_session_analysis():
    """Return the selected analysis from session

    Returns:
        json: Key analysis gives The name of the analysis or None if there is no session available
    """
    if request.method == 'GET':
        sys = session.get("sel_analysis")
        if sys == None: sys = ""
        response = jsonify({"analysis": sys})
        response.headers.add('Access-Control-Allow-Origin', '*')
        return response

Javascript:

/**
 * Function to get the cookie from server and check if current selected analysis is the same as the chosen one in the form, if not reload the page to show the selected analysis
 */
async function getSessionAnalysisAndReload() {
    var analysis = await fetch('http://localhost./api/get-session-analysis', {
            method: 'GET',
            credentials: 'same-origin'
    }).then((response) => {
            j = response.json();
            return j;
        }).then((myJson) => {
            var s = myJson['analysis']   " ";
            if (s != $('#p_sel_sys').text().replace("Currently selected analysis:  ", "")) {
                location.reload();
            }
            return s;
        });
}

HTML:

<script>
window.onfocus = function () {
    getSessionAnalysisAndReload();
}
</script>

I know the session from server is just sending the session from the browser and fetching it again so i could use javascript to fetch the session directly to skip the entire fetch, but this way i can use server sessions without having to change any javascript and just change the python function instead.

  • Related