posting input data from html to python script with ajax - python

I am wanting to POST a user inputted data in an html file to a Python script with AJAX and have the Python script return it so that it shows up in a specific div in the html file.
HTML
<!DOCTYPE HTML>
<html>
<head>
<title>AJAX Test</title>
<script src="http://code.jquery.com/jquery-3.3.1.js"></script>
<script>
function test()
{
var message = $('input[name=message]').val();
$.ajax({
url: "/cgi-bin/hello.py",
type: "POST",
data: {"text" : message},
success: function(response){
$("#div").html(response);
}
});
};
</script>
</head>
<body>
<form>
Enter Message: <input type="text" name="message">
<input type="submit" value="submit" onclick="test()">
</form>
<div id="div">Default Message</div>
</body>
</html>
Python
#!/home/user/virtualenv/test/3.5/bin/python
import cgi, cgitb
cgitb.enable()
data = cgi.FieldStorage()
print "Content-Type: text/html\n"
print data
When I type a message into the input box and press the submit button, nothing happens. I am new to this so I feel like I am probably not understanding how this works. Any help would be appreciated!
Edit: Console is showing Uncaught TypeError: $.ajax is not a function
Edit 2: The first problem was due to using the slim version of jquery. After fixing that, nothing is happening on the page when I input and click submit.

The problem was that the form was submitting when I clicked the button. The solution was to change the input type to <button value="Submit" onclick="test()">.
The next problem was that python was returning FieldStorage(None, None, [MiniFieldStorage('text', 'blahblah')]). The solution was to access the value by using print (data["text"].value)

Related

Form Handling with Lambda-AWS

I am trying to build a Lambda that displays a simple html form, where you fill your name (Mary for example) and the output should be "welcome Mary" but I dont know how to do it without .php
some information:
1.i am using python.
2.the first if (==GET) works fine.
3.action="lambda's URL", omitted in the code below.
4.my problem is on the second if(==POST).I dont know how to collect form data after submitting my HTML form.
Thanks in advance;)
here is the code:
import json
def lambda_handler(event, context):
if event['requestContext']['http']['method'] == 'GET':
content='''
<html>
<body>
<form action="my lambda's URL here" method="POST">
Name: <input type="text" name="fname"><br>
<input type="submit">
</form>
</body>
</html>
'''
if event['requestContext']['http']['method'] == 'POST':
content='''
<html>
<body>
<p>
"I would like to see:"Welcome Mary" here but i don't know how!
</p>
</body>
</html>
'''
# TODO implement
response = {
"statusCode": 200,
"headers": {
'Content-Type': 'text/html',
},
If your code you're accessing parts of the request like the HTTP method.
The event actually holds a heap of different bits of information about the request. You can see an example in the Lambda developer guide.
I would suggest printing out the entire event to start with while you get used to the format. Then work out how to access the form data.

Blank page running python script

I have a HTML-page from which I pass some input values to a python script to be processed there. What I want to do is to show the results of the calculations. Just on a white page. No formatting or anything. Just plain numbers.
The problem is that I am getting just a blank page and I can't figure out why.
I did a lot of research but none of the solutions provided applied direclty to my issue.
It seems that the values are being passed on and processed since i don't get an error message nor there is an error in the error log nor any indications in the web console.
I am running a LAMP webserver which apache2 on it. The apache2 is correctly configured for running python and cgi.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Eval Main</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(function()
{
$('#ok').click(function()
{
$.ajax(
{
url: "/cgi-bin/verlauf_Grenzen.py",
data:
{
a_test: $("#testa").val(),
v_test: $("#testv").val(),
s_test: $("#tests").val(),
j_test: $("#testj").val()
},
success: function(response)
{
handleResponse(response);
}
});
});
});
</script>
<form action="/cgi-bin/verlauf_Grenzen.py" method="POST">
<input id="testa" type="number" name="a" />
<input id="testv" type="number" name="v" />
<input id="tests" type="number" name="s" />
<input id="testj" type="number" name="j" />
<button id="ok" type="submit" value="Submit">Click</button>
</form>
</body>
</html>
verlauf_Grenzen.py
#!/usr/local/bin/python3.6
import json, time, glob, os
import numpy as np
from ruck import Cases
import cgi, cgitb
cgitb.enable()
print("Content-type:text/html\n")
def index(req):
form = cgi.FieldStorage()
a = form.getvalue('a_test')
v = form.getvalue('v_test')
s = form.getvalue('s_test')
j = form.getvalue('j_test')
cases = Cases(a,v,s,j)
#does something here
return x #x ist a single number
print("<html>")
print("<head>")
print("<title>CALC</title>")
print("</head>")
print("<body>")
print("<h2>Your name is {} </h2>".format(x))
print("</body>")
print("</html>")
req.write(x)
ruck.py
#!/usr/local/bin/python3.6
import cgi, cgitb
cgitb.enable()
class Cases(object):
def __init__(self, a, v, s, j):
self.a = a
self.v = v
self.s = s
self.j = j
# does something here (a few functions/methods)
return x, tj, ta, tv, tg, self.v, self.a
def __call__(self):
self.case_one()
self.case_two()
self.case_three()
self.case_four()
Both scripts work fine and cause no errors.
Thanks for any help in advance. I am pretty new in web programming.
There are several things wrong here, both in the JS and the Python.
Firstly, on the JS side, your event handler doesn't prevent the default submission of the form - you should use event.preventDefault(). Secondly, you don't seem to have defined the handleResponse() function that you call within the Ajax success method.
On the Python side, your verlauf_Grenzen file defines an index function but does not seem to ever call it. Inside that function, there is a return x statement halfway down which returns unconditionally, so none of the subsequent code that prints the response will ever be executed.
Finally, if you are doing anything more than trivial work, you should really consider a proper Python micro-framework such as Flask rather than using CGI.
How I solved it:
Python:
import json, time, glob, os
import numpy as np
from ruck import Cases
import cgi
form = cgi.FieldStorage()
a = form.getvalue('a_test')
v = form.getvalue('v_test')
s = form.getvalue('s_test')
j = form.getvalue('j_test')
cases = Cases(a,v,s,j)
# does something here (a few functions/methods)
json.dumps(somedata)
ajax in my HTML:
<script>
$(function(){
$('#btn2').click(function(){
$.ajax({
url: 'https://192.168.80.27/cgi-bin/verlauf_Grenzen.py',
type: 'post',
data: $.('.senddata').serialize(),
success: function(data) {
window.alert("Data sent!");
},
});
});
});
</script>
<input id="btn2" class="button" type="button" value="Send Values" value="Click"/>
<script>
$(function(){
$('#btn').click(function(){
$.ajax({
url: 'https://192.168.80.27/cgi-bin/verlauf_Grenzen.py',
type: 'json',
data: {},
success: function(data) {
var jsondata = JSON.stringify(data);
$('#xbtn').html(jsondata);
window.alert("Success!!!");
},
});
});
});
</script>
<input id="btn" class="button" type="button" value="Load results" value="Click"/>
<span id="xbtn"></span>

Python, Flask: TypeError: 'NoneType' object has no attribute '__getitem__' for filled form

I have looked through previous questions involving the same error, but have not managed to find a working solution for my problem. I have a form in my html code (as part of a single-page-application) that I wish to submit to my python server through ajax.
the form in details.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>A Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">`
<link href= {{ url_for("static",filename="css/bootstrap.min.css") }} rel="stylesheet" media="screen">
</head>
<body>
<div>
<form method="post">
<label for="address">Address</label>
<input class="form-control" type="text" name="address">
<label for="postalcode">Postal Code</label>
<input class="form-control" type="text" name="postalcode"><br>
<label for="city">City</label>
<input class="form-control" type="text" name="city">
<label for="country">Country</label>
<input class="form-control" type="text" id="country_indicator" placeholder="Country" name="country">
<button id="submitForm" type="submit">Submit</button>
</form>
</div>
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
<script src={{ url_for("static", filename="js/bootstrap.min.js") }}></script>
<script src={{ url_for("static", filename="js/details.js") }}></script>
</body>
</html>
If I remove 'method="post"' from the html form, the page empties the forms and reloads, but with it I get the above mentioned error, even when the form is fully filled out. My guess is that something between the form and the JS is not working as the request.json always returns NoneType objects.
details.js:
$(document).ready(function() {
$("#submitForm").click(function(){
var address = $("#address").val();
var postalcode = $("#postalcode").val();
var city = $("#city").val();
var country = $("#country").val();
console.log(address);
var details = {
"address" : address,
"postalcode" : postalcode,
"city" : city,
"country" : country
}
console.log(details.city);
$.ajax({
type: "POST",
url: "/details",
data: JSON.stringify(details, null, '\t'),
contentType: 'application/json;charset=UTF-8',
success: function(result) {
console.log(result)
}
})
})
})
Note: I added the console.log for troubleshooting, but no text appears in the js-console, which is why I believe the problem appears already before this point.
the relevant app.route in my .py file: I am not yet using the values from details.js, I just wish to see that something is actually sent. This is why I only return "ok" for now.
#app.route('/details', methods=['GET', 'POST'])
def details():
if request.method == "POST":
print(request.json['address']) # . TypeError: 'NoneType' object has no attribute '__getitem__' - crash appears here.
return "ok")
return render_template("details.html")
So because of some problem in the previous steps, the object sent to the .py file is NoneType I assume. I am very new to python and JS, so any pointers would be greatly appreciated. Thank you in advance!
Edit: I also encountered "uncaught ReferenceError: $ is not defined" now from the javascript console, but moving the jquery- to the head solved that problem
Doh! The data isn't being sent to the server properly! I've rewritten some of your code below. I hope you don't mind, but the form will now submit with ordinary post variables instead of JSON.
#app.route('/details', methods=['GET', 'POST'])
def details():
# This is our new method, notice it's a bit streamlined.
if request.method == "POST":
# We can get the post data using request.form.get(). The first variable is the name="" attribute in HTML, and the second is the default value if it wasn't found in the data.
return "The address was %s" % request.form.get('address', 'not provided! :O')
return render_template("base.html")
Now for the Javascript!
$(document).ready(function() {
$("#submitForm").click(function(e){
// Prevent the HTML page from submitting the form since we're doing this by AJAX. This would cause duplications and other issues.
e.preventDefault();
// Get a FormData object from the page
var data = new FormData($('form')[0]);
// You don't HAVE to send your data by JSON, and in this instance it will be easier not to
$.ajax({
type: "POST",
url: "/details",
data: data,
processData: false,
contentType: false,
success: function(result) {
console.log(result)
}
})
})
})
Hope this helps! Don't forget to mark the answer as solved if this fixes it for you. :)

Web interface with python backend

I developed a simple application in Python (with a Tkinter interface). But now I want provide a web interface for the same. I know that the python script will wun on the server as CGI. But I would like everything to happen on one page i.e. something like this:
There is a text box for the user to provide input
When a submit button is clicked, the python script runs on the input and generates the output
The output is displayed on the same page without the page reloading
I think Ajax can be used to do this (and I'll learn it if that's the only way), but is there any easier way to do this? I tried generating the front end in python, and linking the button to a function in the same script but that doesn't work...
Thanks
PS: Sorry if the title and the tags are a bit misleadsing...i wasn't so sure what to pick...
EDIT: I tried this but it doesn't work
#!/usr/bin/python2
import cgi
print 'Content-type: text/html'
print """
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
"""
data = cgi.FieldStorage()
sometext = data['sometext'].value
if sometext != '':
print "<p>" + sometext + "</p>"
print """
<form action="test.py" method="post">
<input type="text" name="sometext">
<input type="submit">
</form>
</body>
</html>
"""

Web Form with Web.py on PythonAnywhere

I'm trying to make a simple web script using the PythonAnywhere.com's web.py platform.
My intention is to create a simples Form which gets the data of textboxes and is able to work with them just like we do with PHP and so.
This is my main script:
import web
from web import form
import MySQLdb
render = web.template.render('/home/user/templates/')
conn = MySQLdb.connect("mysql.server","user","*********","userdb")
curs = conn.cursor()
curs.execute('''create table if not exists Dados (
id int not null auto_increment primary key,
nome varchar(200),
item1 varchar(50),
item2 varchar(50),
item3 varchar(50),
item4 varchar(50),
item5 varchar(50));
''')
urls = (
'/', 'index'
)
formula = form.Form(
form.Textbox('Nome', id='nome'),
form.Textbox('Item 1', id='it1'),
form.Textbox('Item 2', id='it2'),
form.Textbox('Item 3', id='it3'),
form.Textbox('Item 4', id='it4'),
form.Textbox('Item 5', id='it5'),
)
class index:
def GET(self):
form = formula()
return render.formtest(form)
def POST(self):
form = formula()
return render.finaliza(form['Nome'].value)
# comment out these two lines if you want to use another framework
app = web.application(urls, globals())
application = app.wsgifunc()
Then I have two templates in HTML, this one stores the Form:
$def with (form)
<form name="main" method="post">
$:form.render()
<input type="submit" name="send" id="envia" value="Ok" /> </form>
And this should give the result after the POST:
$def with (nome)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
Congratulations $:nome !
</body>
</html>
Everything works fine until a press the Ok button.
It shows the right template but doesn't show the $nome variable.
You can check this behavior on this link:
http://jonathan_hepp.pythonanywhere.com/
I'm beginning on web.py and PythonAnywhere so there must be something I'm doing wrong but I can't find it out.
Could you please help me out?
Thanks.
EDIT:
I've just find out now that if I pass the textbox value as a string the result is different.
The result page says "Congratulations None!"
That makes me think that actually the POST is not recieving the value I'm typing in the textbox. So the code seems to be ok but somehow I didn't make it right so it cannot reach the value in the form's input.
Still not working.
SOLVED:
Ok. I realized that the form.Form() option doesn't really create and html form output.
Actually when you look at the source code of the formtest page you see that what I supposed was the form appears as a simple .
So I just made the form into the formtest template directly in html an now it works pretty well.
Just a dumb mistake, but if somebody else comes throught it, just do the same.
Thank you all.
It seems like the variable in the finaliza template should actually be "Nome". So:
Congratulations $:Nome !
Might do the trick. Remember to restart your web app on the Web tab of PythonAnywhere after making changes or you won't see them.
I am using the same web.py framework. when I try to access it via localhost and URL after is /templates/tutorial.html
then I can see "send" button but with these $ signs
$def with (form, text)
$:form.render()
$text
Here is tutorial.html
$def with (form, text)
<head>
<title>Python and AJAX tutorial for beginners with webpy and jQuery</title>
<link rel="stylesheet" type="text/css" href="/static/tutorial.css" />
<script type="text/javascript" src="/static/jquery.js"></script>
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery(".button").click(function() {
var input_string = $$("input#textfield").val();
jQuery.ajax({
type: "POST",
data: {textfield : input_string},
success: function(data) {
jQuery('#foo').html(data).hide().fadeIn(1500);
},
});
return false;
});
});
</script>
</head>
<body>
<br>
<form class="form" method="post">
$:form.render()
<input class="button" type="submit" value="send"/>
</form>
<br><br>
<span id="foo">$text</span>
</body>
How I can get the values of these variables ?
$def with (form, text)
$:form.render()
$text

Categories

Resources