Home > Blockchain >  flask Cannot access before initialization
flask Cannot access before initialization

Time:03-14

index.html

  <div >
    <input type="text" id="input" placeholder="Enter expression" value="1 2"/>
    <input type="submit" id="btn" value="Execute"/>
  </div>
  <input type="text" id="output" readonly="readonly">
  
  <script src="{{url_for('static', filename='js/jquery-3.2.1.min.js')}}"></script>
  <script type="text/javascript">
    document.querySelector('#btn').addEventListener('click', (e) => {
      let equation = document.querySelector('#input').value;
      $.ajax({
        url: "/",
        type: "POST",
        data: equation,
        success: function(){
          console.log("successfull POST");
          let result = {{evaluate}}
          document.querySelector('#output').value = result;
        }
      });
    });
  </script>

main.py

from flask import Flask
from flask import url_for, jsonify, render_template, request, json
from math import *

app=Flask(__name__)

@app.route('/', methods=["GET","POST"])
def index() :
  
    evaluate = ""
    if request.method == 'POST':
        toEvalFromJS = request.get_json()
        evaluate = eval(str(toEvalFromJS))
        return render_template('index.html', evaluate=evaluate)
    
    return render_template('index.html')

if __name__ == "__main__":
    app.run(port=10, debug=True)

error

(index):26 successfull POST
(index):28 Uncaught ReferenceError: Cannot access 'result' before initialization
    at Object.success ((index):28:53)
    at i (jquery-3.2.1.min.js:2:28017)
    at Object.fireWith [as resolveWith] (jquery-3.2.1.min.js:2:28783)
    at A (jquery-3.2.1.min.js:4:14035)
    at XMLHttpRequest.<anonymous> (jquery-3.2.1.min.js:4:16323)

I know what the error means but I could only get such far.

I have already read the following questions:

but they did not help me solve my problem.

What I want to do: User input an expression string, then click on the submit button and get the evaluated string back.

How could I get the evaluated string?

I am new to flask, I do it just for practice

CodePudding user response:

Main problem is that you use {{evaluate}} in wrong way. You expect that JavaScript will get data from server and it will replace {{evaluate}} with new value. But it is not true.

Flask replaces {{evaluate}} with empty string and it sends HTML with empty string - and browser when you load page index.html and browser has HTML with empty string (it doesn't know that there was {{evaluate}}).

When $.ajax gets it agains then Flask replaces {{evaluate}} in template index.html and it sends new HTML with new value in place of {{evaluate}} but it can't replace empty string which you already have in original HTML in browser - it doesn't work this way.

JavaScript get new HTML in data in sucess: function(data){...} and you have to write code which uses this data. But it could be simpler if you would send ajax to separated URL which send back only result (without other HTML). And then it can display data

sucess: function(data){
   document.querySelector('#output').value = data;
}

Later there is another problem(s).

Ajax sends it with standard header for POST form and Flask see it and it convert data to request.form and it has empty request.get_json (because all is in request.form).

But some chars has special meaning in form and url (ie. is used instead of space) and it automatically unescapes data and it puts space instead of .

To get you have to get raw data using request.get_data()

Or you would have to send ajax with header application/json to use get_json().

      $.ajax({
        ...
        contentType: "application/json; charset=utf-8",        
        ...        
      })

Minimal working code

I use render_template_string instead of render_template to put all in one file - and now everyone can simply copy and run it.

I also use https://cdnjs.cloudflare.com to load jquery so it doesn't need local file with jquery.

from flask import Flask, url_for, jsonify, render_template_string, request, json
from math import *  # `import *` is not preferred

app = Flask(__name__)

@app.route('/')
def index():
    return render_template_string("""
  <div >
    <input type="text" id="input" placeholder="Enter expression" value="1 2"/>
    <input type="submit" id="btn" value="Execute"/>
  </div>
  <input type="text" id="output" readonly="readonly">
  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP u1T9qYdvdihz0PPSiiqn/ /3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

  <script type="text/javascript">
    document.querySelector('#btn').addEventListener('click', (e) => {
      let equation = document.querySelector('#input').value;
      $.ajax({
        url: "/data",
        type: "POST",

        contentType: "application/json; charset=utf-8",        

        data: JSON.stringify(equation),
        success: function(data){
          console.log("successfull POST");
          console.log(data);
          document.querySelector('#output').value = data;
        }
      });
    });
  </script>
""")

@app.route('/data', methods=['POST'])
def data():
    print('json:', request.get_json())  # `None` if there is no `contentType: "application/json; charset=utf-8"` in `$.ajax`

    print('data:', request.get_data())
    print('form:', request.form)

    equation = json.loads(request.get_data().decode())
    print('equation:', equation)
    
    if equation:
        result = eval(equation)
    else:
        result = "wrong data"
        
    return jsonify(result)

if __name__ == "__main__":
    #app.debug = True
    app.run(port=5010)
  • Related