Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ajax in Brython

Tags:

ajax

brython

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.

like image 828
chemist Avatar asked Sep 24 '14 16:09

chemist


2 Answers

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)
like image 123
marqueemoon Avatar answered Oct 05 '22 23:10

marqueemoon


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 )

like image 38
jsbueno Avatar answered Oct 05 '22 23:10

jsbueno