So I am getting user input from a template that uses css and jQuery, then I'm posting that data back supposedly on click. However, I am not able to access the data as I believe it is not being posted back.
I believe my ajax code is not recognizing the click, can someone please help me out. I spent the whole day trying to figure out what am I doing wrong.
#This is main code
from bottle import run, route, request, template, static_file, post
def main():
#This is main code
#route('/assets/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='./Gui/assets')
#route('/')
def home():
return template('indexTest')
#post('/home')
def home():
radius=request.forms['radius']
noTr=request.forms['noOdTurbines']
result=radius+noTr
return ({'result': result})
if __name__ == '__main__':
main()
run(host='localhost', port=8080, debug=True)
this is jQuery code
<!DOCTYPE html>
<html>
<head>
<title>AJAX Example</title>
<script type="text/javascript">
$(document).ready(function(){
$('form').on('submit',(function(event){
$.ajax({
type: "POST",
url: "/home"
data: {
radius: $('#radius').val(),
noOfTurbines: $('#noOfTurbines').val()
},
error:function(){
alert('Error: something is wrong with values!!')
}
})
event.preventDefault();
});
}));
</script>
</head>
<body>
<form method="POST" action="/home">
<div id="exampleAccount" role="tabpanel">
<div id="exampleAccountForm">
</div>
<div>
<label for="radius">Radius of Swept-Area of Wind turbine:
</label>
<input type="text" id="radius" required>
</div>
<div >
<label for="noOfTurbines">Number of Wind turbines: </label>
<input type="text" id="noOfTurbines" required>
</div>
</div>
</div>
<div >
<button type="submit" class="btn btn-default"
id="submit">Finish</button>
</div>
</form>
</body>
</html>
I have problems with the request.forms type of multidict, so I convert to dict and this solves all my problems. I usually merge the post and string URL objects into one just to make it more flexible.
def merge_dicts(*args):
result = {}
for dictionary in args:
result.update(dictionary)
return result
payload = merge_dicts(dict(request.forms), dict(request.query.decode()))
Just remember, that bottle uses the name not the id of the form element in a post. So make sure all inputs have a name.
(Which I do not see in your example)
Related
I am new to building API. I am building a very Simple API: When executed, The HTML page displaying API will ask to enter name: the Api will just return: "Hello {name}". I am getting 405 Error. Here is my code for App.py and HTML page:
from app import app
from flask import render_template
from flask import request
#app.route('/')
def home():
return "hello no world!"
#app.route('/template',methods=['POST','GET'])
def template():
output = [request.form.values()]
output = output[0]
return render_template('home.html',prediction_text='Hello {}'.format(output))
and my HTML code for home.html:
!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Welcome home</title>
</head>
<body>
<div class="login">
<h1>Enter your name</h1>
<!-- Main Input For Receiving Query-->
<form action="{{ url_for('template')}}"method="post">
<input type="text" name="name" placeholder="Name" required="required" />
<button type="submit" class="btn btn-primary btn-block btn-large">Enter</button>
</form>
<br>
<br>
{{ prediction_text }}
</div>
</body>
</html>
I have looked at several other StackOverflow forums with just this issue. It seems like there is something wrong with "GET" or "POST" method but I can not seem to figure out what? Maybe one of you could see something I did not. I am running this API Inside a Docker so "app = Flask(name)" are stored elsewhere , If that is relevant.
Method Not Allowed - The method is not allowed for the requested URL
Flask - POST - The method is not allowed for the requested URL
https://www.reddit.com/r/flask/comments/a04aew/ask_flask_help_me_to_find_the_error_in_my_code/
This question is now resolved. I changed two things:
From HTML:
Changing:
<form action="{{ url_for('template')}}"method="post">
to
<form action="{{ url_for('template')}}"method="get">
And Changing from Flask API:
output = [request.form.values()]
output = output[0]
return render_template('home.html',prediction_text='Hello {}'.format(output))
to
output = request.args.values()
return render_template('home.html',prediction_text="Hello {}?".format(list(output)[:]))
I have a Python code.
import cx_Oracle
import re
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__)
app.config['SECRET_KEY'] = 'd369342136ecd032f8b4a930b6bb2e0e'
#app.route('/add')
def edited():
connect = cx_Oracle.connect("********", "********", "******/XE")
cursor = connect.cursor()
cod_ed = request.form['cod_ed']
nome_ed = request.form['nome_ed']
endereco = request.form['endereco']
telefone = request.form['telefone']
cidade = request.form['cidade']
execute = """INSERT INTO editor VALUES
(:cod_ed, :nome_ed, :endereco, :telefone, :cidade)"""
cursor.execute(execute, {'cod_ed':cod_ed, 'nome_ed':nome_ed, 'endereco':endereco, 'telefone':telefone, 'cidade':cidade})
connect.commit()
#app.route('/', methods=['GET', 'POST'])
def add_data():
return render_template('forms.html')
#app.route('/post_data', methods=['GET','POST'])
def post_data():
return redirect(url_for('edited'))
if __name__ == "__main__":
app.run(host = 'localhost', port = 8000, debug=True)
And its html correspondante:
<!DOCTYPE html>
<html>
<head>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous">
</script>
<title>Base de dados</title>
</head>
<body>
<form methods="POST" action="/post_data">
<div class="col-lg-2">
<div class="form-group">
<label for="element-1" >Codigo:</label>
<input id="cod_ed" name="cod_ed" type="text" class="form-control" placeholder="Codigo"/>
<label for="element-2" >Nome:</label>
<input id="nome_ed" name="nome_ed" type="text" class="form-control" placeholder="Nome"/>
<label for="element-3" >Endereço:</label>
<input id="endereco" name="endereco" type="text" class="form-control" placeholder="Endereço"/>
<label for="element-4" >Telefone:</label>
<input id="telefone" name="telefone" type="text" class="form-control" placeholder="Telefone"/>
<label for="element-5" >Cidade:</label>
<input id="cidade" name="cidade" type="text" class="form control" placeholder="Cidade"/>
<input class="btn btn-info" type="submit" value="Enter">
</div>
</div>
</div>
</form>
</body>
</html>
I'm relatively new to Flask and Python in general. When I run the forms, they get displayed, but when I try to insert them into the database, I get this:
werkzeug.exceptions.HTTPException.wrap.<locals>.newcls: 400 Bad Request: KeyError: 'cod_ed'
What exactly is causing it and how do I fix it?
When posting to /post_data endpoint the browser recieves a redirection code, and then gets /add without posting any data, provoking a key error.
You are fetching form elements at the wrong place. You should do the database insertion logic inside /post_data and redirect to /add afterwards.
Here you are posting the form data to /post_data and redirect it to /add so the edited function will not be able to access the request object containing the form data. So just change the form action to /add to make it work correctly.
Supposing I have the following Form. Is there a better way to send the value of the input in the URL like in the example "indication_effects/+MY_VALUE" and get rid of the parameter indication=MY_VALUE ?
Maybe it is possible to do it with Django or should I simply use a django form?
Thank you,
<form id="indication-form" class="form-horizontal" method="get">
<div class="form-inline">
<div class="col-md-8">
<input type="text" class="form-control" id="indication-input" name="indication" />
<button class="btn btn-primary" type="submit" id="indication-submit">Submit</button>
</div>
</div>
</form>
var indicationForm = $('#indication-form');
$("#indication-submit").on("click", function () {
indicationForm.attr("action", "indication_effects/" + $("#indication-input").val());
indicationForm.submit();
});
Look, the GET request always will send the form data through url and the POST request always will send the form data through request headers.
It may not look pretty, but it's the way it works.
However, you can do something nice with Vue.js to get what you want.
Disregard your form action, change your submit button from <button> to <a> and build its href dynamically, you can "submit" your form using the form data on your HTML.
Something like this:
<div id="app">
<form id="indication-form" class="form-horizontal" method="post" action=".">
<div class="form-inline">
<div class="col-md-8">
<input type="text" class="form-control" id="indication-input" name="indication" v-model="indication" />
<a :href="getUrl" class="btn btn-primary" id="indication-submit">Submit</a>
</div>
</div>
</form>
</div>
<script src="//unpkg.com/vue"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
indication: '' // Link all your form fields with v-model here
},
computed: {
getUrl: function() {
return '/' + this.indication + '/'; // Build your url
}
}
});
</script>
Vue.js is a powerful and simple Javascript framework, I like it very much.
I'm building a python flask app implementing user log in , after user log in succefully, it will redirect to userHome.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Python Flask Bucket List App</title>
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
<link href="../static/css/signup.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="header">
<nav>
<ul class="nav nav-pills pull-right">
<li role="presentation" class="active">Logout
</li>
</ul>
</nav>
<h3 class="text-muted">Python Flask App</h3>
</div>
<div class="jumbotron">
<h1>Welcome Home !!</h1>
</div>
<footer class="footer">
<p>© Company 2015</p>
</footer>
</div>
</body>
</html>
and the python code to perform return render_template('userHome.html')
in validateLogin :
#app.route('/validateLogin',methods=['POST'])
def validateLogin():
cursor = None
try:
_username = request.form['inputName']
_password = request.form['inputPassword']
# connect to mysql
conn = mysql.connect()
cursor = conn.cursor()
cursor.callproc('sp_validateLogin',(_username,_password))
data = cursor.fetchall()
if len(data) > 0:
return render_template('userHome.html')
else:
return render_template('error.html', error = "Wrong Username or
Password")
except Exception as e:
return render_template('error.html',error = str(e))
finally:
if cursor:
cursor.close()
conn.close()
and the signin.js :
$(function(){
$('#btnSignIn').click( function(){
$.ajax({
url: '/validateLogin',
data: $('form').serialize(),
type: "POST",
success: function(response){
console.log(response);
},
error: function(error){
console.log(error);
}
});
});
});
and finally the signin.html:
!DOCTYPE html>
<html lang="en">
<head>
<title>Sign In</title>
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
<link href="../static/signup.css" rel="stylesheet">
<script src="/static/js/jquery-3.1.1.js"></script>
<!--<script src="/static/js/jquery-3.1.1.min.map"></script>-->
<script src="/static/js/signin.js"></script>
</head>
<body>
<div class="container">
<div class="header">
<nav>
<ul class="nav nav-pills pull-right">
<li role="presentation" >Home</li>
<li role="presentation" class="active">Sign In</li>
<li role="presentation">Sign Up</li>
</ul>
</nav>
<h2 class="text-muted">Release Control System</h2>
</div>
<div class="jumbotron">
<h1>Log In</h1>
<form class="form-signin">
<label for="inputName" class="sr-only">Name</label>
<input type="name" name="inputName" id="inputName" class="form-control" placeholder="Name" required autofocus>
<!--<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" name="inputEmail" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>-->
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="inputPassword" id="inputPassword" class="form-control" placeholder="Password" required>
<button id="btnSignIn" class="btn btn-lg btn-primary btn-block" type="button">Sign in</button>
</form>
</div>
<footer class="footer">
<p>Copyright 2017 Foxconn CABG © All Rights Reserved.</p>
</footer>
</div>
</body>
</html>
but when I log in successfully it does not direct to the userHome.html page, it showed all html entities instead. Meaning the templates are working but the browser is treating wrongly.
I've tried many tricks like:
headers = {'Content-Type': 'text/html'}
return make_response(render_template('userHome.html'),200,headers)
but it still returns html entities, not html page.
This has confused me for days, thanks in advance.
Since I don't know how to send a redirect request to ajax and execute it. I will simply share the way I do things.
# Python Code
#app.route('/login')
def login():
# check if user is not logged in then render the login form
if user_not_logged_in():
return render_template('login_form.html')
# if user logged in, then redirect to userHome
else:
return redirect(url_for('userHome'))
from flask import jsonify
#app.route('/validateLogin', methods=['POST'])
def validateLogin():
# do some stuff and check for validation
if stuff_goes_well:
return jsonify({'data': 'success'})
else:
return jsonify({'data': 'failure'})
#app.route('/userHome')
def userHome():
# check if user is logged in
if logged_in_user_session_exists():
return render_template('userHome.html')
else:
# user is not logged in so redirect him to the login page
return redirect(url_for('login'))
# jQuery code
$.ajax({
url: "/validateLogin",
type: "POST",
dataType: "json",
data: data_here,
success: function(response){
if(response.data == 'success'){
# success was sent so the user logged in successfully, redirect to user home
window.location.replace('/userHome');
}else{
# there was an error in the logging in
alert('there was an error!');
}
}
});
To sum it up in a few words: simply send your data with ajax to Python. then let Python handle verification and the analysis of the data. then if all goes well, tell jQuery " hey it's all cool here " ( which is represented by the 'success' string we send ). if something was wrong then we tell jQuery that we had a problem hence the 'failure' string we send. then in jQuery we act upon the string that was sent. if it was success, then we redirect the user to the desired URL ( which is /userHome in this case ). if failure was sent then we say there was an error.
Please notice that these python checks are important so the user just doesn't type "/userHome" in the URL and be able to just view the page while he is not logged in.
I hope you find this useful.
Until recently I was able to post data to my datastore (Google App Engine). I've now added summernote wysiwyg and now I'm no longer able to add/fetch data from the datastore. Where do you think the problem is?
Main.py
class About(ndb.Model):
text = ndb.StringProperty()
#object
cv = About()
class MainHandler(webapp2.RequestHandler):
def get(self):
title="Exercise"
cv = About.get_or_insert('6684480941064192')
text = cv.text
template_vars={'title': title, 'text':text}
template = JINJA_ENVIRONMENT.get_template('home.html')
self.response.out.write(template.render(template_vars))
def post(self):
cv = About.get_or_insert('6684480941064192')
cv.text=self.request.get("texto")
cv.put()
self.redirect('/')
Html (Material design + bootstrp)
<form class="col s12" form action="/" method="POST" id="frmPost" style="margin-top:25px; margin-bottom:10px;">
<div class="row">
<div class="panel panel-heading" style ="border-radius: 0px; background-color: #e57373;">
<h3 class="panel-title" style ="color: white;">About...</h3>
</div>
<textarea rows="10" id="summernote" form="frmPost" name ="texto" style="margin-top:-10px; display:block;">
{{text}}
</textarea>
</div>
</form>
<script>
$(document).ready(function() {
$('#summernote').summernote({
});
});
</script>
Not sure what summernote is but you probably need to POST your data back to the server somewhere in your HTML/JS. You have the <form> but there doesn't seem to be a way to submit your data back to GAE. You possibly need something like <input type="submit" value="Save Data" /> somewhere inside your <form/>.