I'm trying to load forms in modal dynamically using jquery and ajax in python but when i submit the form i get the error werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand. KeyError: 'title'.
Mentioning that I recently started using jquery and ajax with python, could you help me please?
I want to reuse modal section to load multiple forms with jquery.
The code is as below.
HTML: lockbox.html
<input class="btn add" type="button" value="New">
<!--Modal-->
<dialog class="modal">
<div class="modal-header">
<h4 class="modal-title"></h4>
<button class="close-modal">X</button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button class="close-modal">Cancel</button>
</div>
</dialog>
Javascript
$('.add').on('click', function () {
$.ajax({
type: "get",
url: "/newentry",
success: function (data) {
$('.modal-body').html(data);
$('.modal-header').css('background-color', '#0688fa');
$('.modal-title').text('New register');
$('.modal-footer').css('background-color', '#0688fa');
modalBox.showModal();
}
});
});
Python route
#app.route('/newentry')
def newentry():
return render_template('app/addpass.html')
HTML: addpass.html
<form method="post" class="addPass" action="/addPassReg">
<div class="field-block">
<label for="title">Title: </label>
<input type="text" id="title" value="">
</div>
<div class="field-block">
<label for="user">User: </label>
<input type="text" id="user" value="">
</div>
<div class="field-block">
<label for="passw">Password: </label>
<input type="text" id="passw" value="">
</div>
<div class="field-block">
<input type="submit" value="Save" class="btn save">
</div>
</form>
Python route
#app.route('/addPassReg', methods = ['POST', 'GET'])
def addPassReg():
#cur = mysql.connection.cursor()
if request.method == 'POST':
print('is post')#for debug
print(request.args.listvalues)#trying to know the error
title = request.form['title']
user = request.form['user']
passwd = request.form['passw']
if title and user and passwd:
return json.dumps({'message' : 'OK.'})
else:
print('After')
return redirect(url_for('lockbox'))#json.dumps({'html' : 'Complete please.'})
if request.method == 'GET':
print('is get')#for debug
else:
print('whats up?')#for debug
return redirect(url_for('lockbox'))
When I reuse the modal just to see data it's OK, but for forms I realize that it doesn't work and I don't know if it doesn't recognize the form data or I'm doing something wrong.
Related
I'm learning javascript/jquery on the go, I'm trying to reload a form but keeping its js properties (required and masked inputs), code and pictures attached.
First image: Masked inputs works like a charm
Second image: The form its fully filled, still working
Third image: The form it reloaded, but no properties applied
The html form (minmized, just the first field)
<div class="card-body" id="clientsAddFormContainer">
<form method="post" action="main/clients/addController.php">
<div class="form-group row" id="clientRutDiv">
<div class="col-lg-6">
<div class="form-group" id="clientRutInnerDiv">
<label class="col-form-label" for="clientRut">RUT <span class="required">*</span></label>
<input type="text" name="clientRut" id="clientRut" class="form-control" placeholder="Ej. 11.111.111-1" required="" data-plugin-masked-input="" data-input-mask="99.999.999-*" autofocus>
</div>
</div>
</div>
</div>
</form>
<footer class="card-footer">
<div class="switch switch-sm switch-primary">
<input type="checkbox" name="wannaStay" id="wannaStay" data-plugin-ios-switch checked="checked" />
</div> Mantenerme en esta página
<button type="button" style="float: right;" class="btn btn-primary" onclick="realizaProceso();">Enviar</button>
</footer>
The JS for realizaProceso()
function realizaProceso(){
var validator =0;
validator += validateRequiredField('clientRut');
if(validator == 0){
var parametros = {
"clientRut" : document.getElementById('clientRut').value,
"tableName" : 'clients'
};
$.ajax({
data: parametros,
url: 'route/to/addController.php',
type: 'post',
success: function (respText) {
if(respText == 1){
if(document.getElementById('wannaStay').checked){
$("#clientsAddFormContainer").load(location.href + " #clientsAddFormContainer");
}else{
window.location = "linkToOtherLocation";
}
}else{
showNotyErrorMsg();
}
},
error: function () {
showNotyErrorMsg();
}
});
}else{
showNotyValidationErrorMsg();
}
}
So my JS check all fields are validated, then prepare the array, and wait for the php binary response, 1 means the data has been inserted to db, if wannaStay is checked reload the div "clientsAddFormContainer" but as I said, it loose the properties.
Please sorry for my grammar or any other related english trouble, not a native english speaker.
Ps. I've removed some code so it could go different than the images.
Thanks in advance!
EDIT!
The original code is
<div class="card-body" id="clientsAddFormContainer">
<form method="post" action="main/clients/addController.php">
</form>
</div>
one the js exec I got
<div class="card-body" id="clientsAddFormContainer">
<div class="card-body" id="clientsAddFormContainer">
<form method="post" action="main/clients/addController.php">
</form>
</div>
</div>
2nd EDIT
I found the answer in other stackoverflow question
I created the following HTML form inside a jqxWindow widget for a Laravel project:
<div id="provinceWindow">
<div id="provinceWindowHeader"></div>
<div id="provinceWindowContent">
<form id="provinceForm" method="POST" action="{{route('province.store')}}">
{{ csrf_field() }}
<input type="hidden" name="provinceId" id="provinceId" value=""/>
<div class="form-group row">
<div class="col-6"><label>English province name</label></div>
<div class="col-6"><input type="text" name="provinceNameEn" id="provinceNameEn" maxlength="20"/></div>
</div>
<div class="form-group row">
<div class="col-6"><label>Spanish province name</label></div>
<div class="col-6"><input type="text" name="provinceNameSp" id="provinceNameSp" maxlength="20"/></div>
</div>
<br/>
<div class="form-group row justify-content-center">
<input type="button" value="Submit" id="submitBtn" class="btn btn-sm col-3" />
<span class="spacer"></span>
<input type="button" value="Cancel" id="cancelBtn" class="btn btn-sm col-3" />
</div>
</form>
</div>
</div>
This is the javascript file:
$(document).ready(function () {
var datarow = null;
$.ajaxSetup({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}
});
//-----------------------------
// Window settings
//-----------------------------
$('#provinceWindow').jqxWindow({
autoOpen: false,
isModal: true,
width: 400,
height: 160,
resizable: false,
title: 'Province name',
cancelButton: $('#cancelBtn'),
initContent: function () {
$('#submitBtn').jqxButton();
$('#submitBtn').on('click', function () {
$('#provinceForm').submit();
});
}
}).css('top', '35%');
The file routes\web.php has only one resourse route defined for this page:
// Routes for province maintenance
Route::resource('province', 'provinceController');
Checking the available routes with php artisan route:list command, I get these:
Method URI Name Action
GET|HEAD / APP\Http\Controllers\homeController#index
GET|HEAD province province.index APP\Http\Controllers\provinceController#index
POST province province.store APP\Http\Controllers\provinceController#store
GET|HEAD province/create province.create APP\Http\Controllers\provinceController#create
GET|HEAD province/{province} province.show APP\Http\Controllers\provinceController#show
PUT|PATCH province/{province} province.update APP\Http\Controllers\provinceController#update
DELETE province/{province} province.destroy APP\Http\Controllers\provinceController#destroy
GET|HEAD province/{province}/edit province.edit APP\Http\Controllers\provinceController#edit
My controller action:
public function store(Request $request)
{
$fields = $request->all();
if ($request->provinceId == '') {
$province = new province($fields);
$validator = Validator::make($fields, $province->rules());
if ($validator->fails()) {
return redirect('')->withErrors($validator)->withInput();
}
else {
$province->save();
}
return view('province/index');
}
}
The form is shown on top of a jqxGrid widget, as a modal window, in order to capture the required information and perform the CRUD operations for the corresponding DB table.
The problem is, when I click the "Submit" button the window is closed and nothing else happens. The form is not posted to the indicated action and the data entered get lost.
It does not matter if I initialize the submitBtn inside the initContent or outside of it. The form is never posted.
I also tried the Close event of the jqxWindow to no avail.
If I take a look to the generated HTML it looks like this:
<form id="provinceForm" method="POST" action="http://mis:8080/province">
<input type="hidden" name="_token" value="Y9dF5PS7nUwFxHug8Ag6PHgcfR4xgxdC43KCGm07">
<input type="hidden" name="provinceId" id="provinceId" value="">
<div class="form-group row">
<div class="col-6">
<label>English province name</label>
</div>
<div class="col-6">
<input type="text" name="provinceNameEn" id="provinceNameEn" maxlength="20">
</div>
</div>
<div class="form-group row">
<div class="col-6">
<label>Spanish province name</label>
</div>
<div class="col-6">
<input type="text" name="provinceNameSp" id="provinceNameSp" maxlength="20">
</div>
</div>
<br>
<div class="form-group row justify-content-center">
<input type="button" value="Submit" id="submitBtn" class="btn btn-sm col-3 jqx-rc-all jqx-button jqx-widget jqx-fill-state-normal" role="button" aria-disabled="false">
<span class="spacer"></span>
<input type="button" value="Cancel" id="cancelBtn" class="btn btn-sm col-3">
</div>
</form>
Pressing the submit button takes me to the home page and nothing gets added to the DB table.
I guess the issue has something to do with Laravel routes because I get no errors.
What is missing or what is wrong with this approach?
Any light is appreciated.
Alright, because I erroneously added in my Model a validation, that was not needed, for a column (there was already a constraint defined at the DB table level), it was not possible to fulfill the validator when saving a new record. I commented that line in my Model and, that was it!
protected $rules = array(
'provinceNameEn' => 'required|alpha|max:20',
'provinceNameSp' => 'required|alpha|max:20'
//'deleted' => 'required|in:M,F' // This is already validated in a DB constraint.
);
I noticed the control was returned to my home page but without any message or error, but if you pay attention to my controller it was precisely the behavior programmed. However, there is no implementation to display the error messages, so I added dd($validator); before that return statement. There I read the message and finally found the solution.
EDIT: Changed the HTML form statement to work like so:
<form action="." class="form-horizontal" id="groupinfoForm" onsubmit="SubmitToServer()" method="post">
Question: Do i still also need the method="post">
Also changed the javascript to work with the onsubmit:
function SubmitToServer() {
event.preventDefault();
//some ajaxy goodness here... still working on this.
$.ajax({
data: $("#groupinfoForm").serialize(),
success: function(resp){
alert ("resp: "+resp.name);
}
})
//I thinK i have to change all this to work inside the .ajax call?
formData = $('form').serializeArray()
$('#group_info option:first').prop('selected',true);
gid = $('#group_info option:selected').val()
//test alert
alert("Submitting data for provider: " + $("#provider_id").val() + " and " + gid + " and " + formData[0]['date_joined']);
$("#groupinfo-dialog").modal('hide');
}
I have a form, that is standard django. Fill it out send it off goes to a different page upon success..shows errors if you don't fill out portions.
Now I have a modal form that will pop up to fill out some extra data. I have decided to try to my hand at ajax for this. I have some of it working:
Inside the class that is an UpdateView:
def post(self, request, *args, **kwargs):
if self.request.POST.has_key('group_info_submit') and request.is_ajax():
print("YOU SURE DID SUBMIT")
return HttpResponse("hi ya!")
The problem is it always redirects to a different page, and fails validation anyway because the form the modal pops over is not complete and trying to be submitted.
I saw this post here:
Ajax Form Submit to Partial View
This seems overly complicated, I just have a small div in my form that is a modal div that I would like to submit sort of separately from the rest... The java script I have in the code:
$.ajax({
data: $("#groupinfoForm").serialize(),
success: function(resp){
alert ("resp: "+resp.name);
}
})
Then the little modal html snippet is:
<div class="container">
<div id="groupinfo-dialog" class="modal" title="Group Information" style="display:none">
<div class="modal-dialog">
<h1> Group Information </h1>
<div class="modal-content">
<div class="modal-body">
<form action="." class="form-horizontal" id="groupinfoForm" method="post">
{% csrf_token %}
{{ group_information_form.non_field_errors }}
<div class="col-md-12">
{{ group_information_form.date_joined_group.errors }}
{{ group_information_form.date_joined_group.label_tag }}
{{ group_information_form.date_joined_group }}
</div>
<div class="col-md-12">
{{ group_information_form.provider_contact.errors }}
{{ group_information_form.provider_contact.label_tag }}
{{ group_information_form.provider_contact }}
</div>
<div class="col-md-12">
{{ group_information_form.credentialing_contact.errors }}
{{ group_information_form.credentialing_contact.label_tag }}
{{ group_information_form.credentialing_contact }}
</div>
<div class="col-md-12">
<div class="col-md-3">
</div>
<div class="col-md-8 form-actions">
<input type='button' class='btn' onclick="CancelDialog()" value='Cancel'/>
<input type='submit' class='btn btn-success' onclick="SubmitToServer()" value='Save' name='group_info_submit'/>
</div>
<div class="col-md-1">
</div>
</div>
<input type="hidden" id="provider_id" name="provider_id" value="{{ provider_id }}" />
<input type="hidden" id="group_id" name="group_id" value="{{ group_id }}" />
</form>
</div>
</div>
</div>
</div>
</div> <!-- end modal Group Info Dialog -->
I do have a model form on the backend in the forms.py here. Also note there was a SubmitToServer() call, that is where I thought I could toss all the ajax stuff over the fence to the server, but I guess I need that $.ajax? I am still learning the deeper parts of jquery. I want to do a lot of preprocessing before i submit the data. My attempt at the submittoserver javascript was here:
Wasn't sure how to get all the form data (just the three fields I care about from the modal) to send it over...my attempt here:
function SubmitToServer() {
formData = $('form').serializeArray()
$('#group_info option:first').prop('selected',true);
gid = $('#group_info option:selected').val()
alert("Submitting data for provider: " + $("#provider_id").val() + " and " + gid + " and " + formData[0]['date_joined']);
$("#groupinfo-dialog").modal('hide');
}
So can I bypass the main form validation and just send the three fields over somehow? and not have it redirect but stay on the page?
You have to intercept the submit event. add onsubmit="someFunction()" to the form. In the someFunction ajax the data you want to validate before submitting, and if all is ok return true, else false.
https://jsfiddle.net/am5f14oc/
<html>
<body>
<form onsubmit="validateFunc()" action="." method="post">
<input id="name" type="text" name="name">
<input type="submit"/>
</form>
</body>
</html>
and the javascript
function validateFunc() {
formData = $('form').serializeArray();
// do ajax or whatever and return true if everything is ok
return false;
}
I'm using a super basic google form on my website. I'm using this website to extract the HTML to display it on my website - http://stefano.brilli.me/google-forms-html-exporter/
Once I hit submit, nothing happens. The page is just locked. I'm trying to resubmit it to another page. Here is my code
<div class="row">
<form action="https://docs.google.com/forms/d/e/1FAIpQLSfJQ9EkDN8aggSL9AEB2PK4BGiZgBzLDbS1IPppfSkU1zy-oA/formResponse"target="_self" id="bootstrapForm" method="POST">
<div class="col-sm-6 col-md-3">
<input id="679075295" type="text" name="entry.679075295" class="form-control" >
</div>
<div class="col-sm-6 col-md-3">
<input id="897968244" type="text" name="entry.897968244" class="form-control" >
</div>
<div class="col-sm-6 col-md-3">
<input id="685661947" type="text" name="entry.685661947" class="form-control" >
</div>
<input id="503500083" type="hidden" name="entry.503500083" value="<%= #investment.id %>" >
<div class="col-sm-6 col-md-3">
<button type="submit" value"submit" class="btn btn--primary type--uppercase" >Get Started</button>
</div>
</form>
Here is the ajax script
<script>
$('#bootstrapForm').submit(function (event) {
event.preventDefault()
var extraData = {}
$('#bootstrapForm').ajaxSubmit({
data: extraData,
dataType: 'jsonp', // This won't really work. It's just to use a GET instead of a POST to allow cookies from different domain.
error: function () {
// Submit of form should be successful but JSONP callback will fail because Google Forms
// does not support it, so this is handled as a failure.
alert('Form Submitted. Thanks.')
// You can also redirect the user to a custom thank-you page:
window.location = 'http://reif.com.au/thankyou'
}
})
})
</script>
</div>
Feeling a little silly on this one. Essentially i didn't copy over all of the scripts. I was rushing through.. ALWAYS number 1 error!
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.2/jquery.form.min.js" integrity="sha256-2Pjr1OlpZMY6qesJM68t2v39t+lMLvxwpa8QlRjJroA=" crossorigin="anonymous"></script>
This is what i needed to add, it now successfully submits and redirects!
I'm trying to let the user download an mp3 file after a text-to-speech convert using gTTS. The flash message appears but the download dialog does not open.
Here is the Python code:
def mytts():
if request.method == 'POST':
if not request.form['text']:
flash('Text needed to proceed', 'error')
else:
text_input = request.form['text']
tts = gTTS(text=text_input, lang='en')
f=TemporaryFile()
tts.write_to_fp(f)
flask.send_file(f,as_attachment=True,attachment_filename="MyTTSOutput.mp3", mimetype="audio/mpeg")
f.close()
flash('Successful Text-to-Speech Convert')
return redirect(url_for('mytts'))
return render_template('mytts.html')
HTML Code (the form part only):
<form action="" method=post class="form-horizontal">
<h2>Convert Text To Speech</h2>
<div class="control-group">
<div class="controls">
<textarea name="text" rows=10 class="input-xlarge" placeholder="Enter text to be converted here" required>{{ request.form.text }}</textarea>
</div>
</div>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-success">CONVERT!</button>
<button type="button" class="btn btn-info">HOME</button>
</div>
</div>
</form>
Please help.
You need to return the result of send_file. It generates a response object, Flask can only do something with that object if it's returned from the view function.
with TemporaryFile() as f:
tts.write_to_fp(f)
return send_file(f, as_attachment=True, attachment_filename="tts.mp3")