7

I am writing a web application using Flask and would like to use browser.ajax functionality in Brython but couldn't find a workable example. It would be very nice if someone demonstrates a short example how to use ajax in Brython. More specifically, how to pass data entered by a user into a textfield to a textarea by clicking submit button. Any help is highly appreciated!


(I am writing this several weeks after I posted the question above). I followed this tutorial on how to implement ajax in Flask (http://runnable.com/UiPhLHanceFYAAAP/how-to-perform-ajax-in-flask-for-python) and tried to replace jquery.ajax by Brython. Unfortunately, I still cannot get it work. Here is my code:

Flask's portion:

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

@app.route('/_add_numbers')
def add_numbers():
    a = request.args.get('a', 0, type=int)
    b = request.args.get('b', 0, type=int)
    return jsonify(result=a + b)

Brython/HTML:

 <body onload="brython()">
 <script type="text/python">
 from browser import document as doc
 from browser import ajax

def on_complete(req):
    if req.status==200 or req.status==0:
        doc["txt_area"].html = req.text
    else:
        doc["txt_area"].html = "error "+req.text

def get(url):        
    req = ajax.ajax()
    a = doc['A'].value        
    b = doc['B'].value
    req.bind('complete',on_complete)
    req.open('GET',url,True)
    req.set_header('content-type','application/x-www-form-urlencoded')
    req.send({"a": a, "b":b})      

doc['calculate'].bind('click',lambda ev:get('/_add_numbers'))

</script>

<div class="container">
  <div class="header">
    <h3 class="text-muted">How To Manage JSON Requests</h3>
  </div>
  <hr/>
  <div>
  <p>
<input type="text" id="A" size="5" name="a"> +
<input type="text" id ="B" size="5" name="b"> =
<textarea type="number" class="form-control" id="txt_area" cols="10" rows = '10'></textarea>
<p><a href="javascript:void();" id="calculate">calculate server side</a>

  </div>
 </div>
 </body>
</html>

What I get is "result":0. It looks like brython does not send data to the Flask's view function but I don't know how to fix that. So, it would be great if some one could point out what exactly I am doing wrong.

Jug
  • 540
  • 3
  • 7
chemist
  • 373
  • 9
  • 20

2 Answers2

6

In your example, the Ajax request is sent with the method GET. In this case, the argument of send() is ignored : the data must be sent in the query string appended to the url

The Brython code should be :

def get(url):        
    req = ajax.ajax()
    a = doc['A'].value        
    b = doc['B'].value
    req.bind('complete',on_complete)
    # pass the arguments in the query string
    req.open('GET',url+"?a=%s&b=%s" %(a, b),True)
    req.set_header('content-type','application/x-www-form-urlencoded')
    req.send()

If you want to use the POST method, then you can keep the Brython code as is, but the Flask code should be modified : you must specify that the function handles a POST request, and you get the arguments with the attribute "form" instead of "args" :

@app.route('/_add_numbers_post', methods=['POST'])
def add_numbers_post():
    a = request.form.get('a', 0, type=int)
    b = request.form.get('b', 0, type=int)
    return jsonify(result = a+b)
marqueemoon
  • 376
  • 2
  • 5
  • Thank you so much! It works! The only question I have is: do I need to manually include arguments in the query string(in this case "?a=%s&b=%s") or it can be done somehow automatically? Again, thanks a lot! – chemist Dec 03 '14 at 15:38
  • You should really prefer the Post method. Either way, yes, the arguments must be included "manually" - The browser only "knows" to collect form values and submit them in an event that reloads the whole page. – jsbueno Jan 26 '15 at 16:15
  • Anyone knows how to set headers? I need to correctly set the headers for: https://developer.oxforddictionaries.com/ – sqp_125 Apr 13 '19 at 15:59
3

I am working on that - there is nothing ready made, but writing Python code makes it really painless.

I can't post the code I am working on, (and it is far from minimal) - but basically, you write a (Br)Python function to iterate on the HTML, or form DOM, and collect everything that has a "value" in a json-nish structure (a dictionary with nested dicionaries and lists at will) - Them you simply use the browser.ajax object as documented in http://brython.info/doc/en/index.html#, and pass the object with your data as a parameter to the "send" method.

The object data will be URLencoded in the request body. You just have to decode it from there to JSON on the client side.

As an extra hint: I did not go deep on the question, but I feel like the URLencoding used by default may fail to express everything that is possible in JSON. So imported brython's json module, and do the send like this:

ajax_object.send({"data": json.dumps(json_data)})

This allows me to do this on the client-side: json_data = json.loads(urllib.unquote(request.body).split(":",1)[-1] )

(the "request.body" is from Pyramid - for flask it is "request.data", but only if the conte-type is not understood by the flask - check How to get data received in Flask request )

Community
  • 1
  • 1
jsbueno
  • 99,910
  • 10
  • 151
  • 209
  • Thank you very much for your reply. I just updated my question by including a Flask/brython sample. Still cannot get it work. – chemist Nov 27 '14 at 21:25