I make an ajax call to my server using the change event on a select widget. Does this cause the Django Form to be invalid? Here is an example of the code.
JAVASCRIPT
<form class="form-horizontal" action="{% url 'accountSelections' %}" method="post">
{% csrf_token %}
<div class="form-group">
<div class="row">
<div class="col-md-4">
{{ account_selection_form|crispy }}
<input class="btn btn-primary" id="button" type="Submit" value="Next >>">
</div>
<div class="col-md-4">
</div>
<div class="col-md-4">
<div id="grid"></div>
</div>
</div>
</div>
</form>`
$( document ).ready(function() {
$("#id_excludeClassification").SumoSelect();
var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
$( "#id_acctFilterName" ).change(function() {
var data = "";
$.ajax({
type:"GET",
url : "../filter",
data : "id="+$(this).val(),
csrfmiddlewaretoken: token,
success : function(response) {
$("#grid").kendoGrid({
data: response,
height: 550,
groupable: true,
sortable: true,
columns: [
{
field: "acctCd",
title: "Code"
}, {
field: "shortName",
title: "Account Name"
}]
});
var grid = $("#grid").data("kendoGrid");
dataSource = new kendo.data.DataSource({
data: response
});
grid.dataSource = dataSource;
dataSource.read();
grid.refresh();
data = response;
return response;
},
error: function() {
alert('Error occured');
}
});
});
});
Does a form submit after cause this to make the form invalid?
My understanding is that you can submit multiple times with the same CSRF token, so it shouldn't be a problem.
you put your csrfmiddlewaretoken variable out data object that you send to your server then it can't work.
Here is what you have to do :
data : {
id : $(this).val(),
csrfmiddlewaretoken: token,
}
Related
Like the title states - I'm trying to get my email collection form on my static webpage to work while hosting on AWS.
The HTML is:
<form id="email-submit" method="post">
<div class="container-fluid">
<div class="row justify-content-end">
<div class="col-lg-6">
<div class="call-action-content text-center">
<h2 class="call-title">Want early access?</h2>
<p class="text">Enter your email below to gain priority access and to receive updates on the official release.</p>
<div class="call-newsletter">
<i class="lni-envelope"></i>
<input type="email" id="email-input" placeholder="Email address">
<button type="submit" onClick="submitToAPI2(event)">Stay informed</button>
And the jquery/ajax I found on Amazon's documentation I'm using is:
function submitToAPI2(e) {
e.preventDefault();
var URL = "the api gateway";
var reeamil = /^([a-zA-Z0-9_.+-])+\#(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (!reeamil.test($("#email-input").val())) {
alert ("Please enter a valid email address");
return;
}
var email = $("#email-input").val();
var data = {
email : email
};
$.ajax({
type: "POST",
url : "api gateway",
dataType: "json",
crossDomain: "true",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
success: function () {
// clear form and show a success message
alert("Successfull");
document.getElementsById("email-submit").reset();
location.reload();
},
error: function () {
// show an error message
alert("Error. Please try again");
}});
}
Any ideas on why it's not working?
I am very new to JS/Ajax and a relative novice to Django. I am testing to see how I can get information back and forth from an Ajax call to my view, and back to Ajax to replace a header string as a simple test.
I can receive information back to my view (h1, which is "AJAX TEST"). What I can't seem to get is the h2text to change to "HEADER CHANGED".
Any help is appreciated as I don't know if it's my Django return function or my Ajax function.
Here is my ajax_test.html:
<div class="content">
<div class="center">
<h1 id="h1">AJAX TEST</h1>
<div>
<button id="btn">PRESS ME</button>
</div>
</div>
<div id="update_div">
{% include "ProdPlat/ajax_test_div.html" %}
</div>
</div>
<script type="text/javascript" src="{% static 'ProdPlat\js\ajax_test.js' %}"></script>
{% endblock %}
My ajax_test_div.html (which I'm trying to refresh):
<div class="content">
<div class="center">
<h2 id="h2">{{h2text.h2text}}</h2>
</div>
</div>
My views_test.py:
def test_ajax(request):
h2text = {'h2text': "INITIAL HEADER"}
if request.method == 'POST':
logger.debug('POST request')
text = request.POST.get('text')
logger.debug('text = {}'.format(text))
h2text = "HEADER CHANGED"
dict = {
'h2text': h2text,
}
# return JsonResponse(dict)
# return render(request, 'ProdPlat/ajax_test_div.html', {'h2text': h2text})
return render_to_response('ProdPlat/ajax_test_div.html', dict)
return render(request, 'ProdPlat/ajax_test.html', {'h2text': h2text})
And finally my Ajax call:
$(document).on('click', 'button', function(){
var csrftoken = getCookie('csrftoken');
console.log('Button Clicked!');
var text = $('h1').text()
console.log('h1 text = ' + text);
$.ajax({
type : 'POST',
url : "/ProdPlat/Ajax_Test/",
dataType: 'json',
data: {'text' : text,
'csrfmiddlewaretoken': csrftoken,
},
success: function(data) {
console.log('data = ' + data);
console.log('data.h2text = ' + data.h2text);
$('#update_div').load(' #update_div')
console.log('Success!');
},
failure: function(data) {
console.log('Failed!');
console.log('data = ' + data);
},
})
})
I'm using a for loop in a template to create multiple forms with method="post" that work with Ajax. But only the form for the first element of items_list works fine, the rest do not work at all showing error 405 0 Method Not Allowed. I think they all should work the same way. And just wondering if this issue was caused by a for loop or something else.
cart_items.html:
<script>
$(document).ready(function () {
$("#remove").click(function (event) {
event.preventDefault();
$.ajax({
url: '{% url "cart:remove_from_cart" %}',
type: "POST",
dataType: 'json',
data: {bookID: $('#idInput').val()},
success: function (response_data) {
alert('works fine')
},
error: function (response_data) {
console.log('error occurred');
}
});
});
});
</script>
{% for book in items_list %}
<div class="items">
<p id="title"> {{ book.book.title }}, quantity: {{ book.quantity }} </p>
<form method="post">
{% csrf_token %}
<input id="idInput" value="{{ book.book.id }}" >
<button id="remove" type="submit"> Remove</button>
</form>
</div>
{% endfor %}
The code in the function body below is just for testing. Once the first form works, I guess the problem was not caused by the function view.
cart/views.py:
#csrf_exempt
def remove_books(request):
cart = Cart.objects.get(user=request.user)
if request.method == 'POST':
passed_id = request.POST['bookID']
secured_id = int(passed_id)
response_data = {
'quantity': secured_id
}
return JsonResponse(response_data)
<script>
$(document).ready(function () {
$(".remove").click(function (event) {
// event.preventDefault(); // don't think it should be required with button type=button
var book_id = $(this).parent().find('.idInput').val(); // find correct input box.
var csrf = $('input[name="csrfmiddlewaretoken"]').val(); // get csrf token in variable.
// there are multiple ways to get csrf token, I personally like this ^^, see https://docs.djangoproject.com/en/2.1/ref/csrf/#ajax for more
$.ajax({
url: '{% url "cart:remove_from_cart" %}',
type: "POST",
dataType: 'json',
data: {
bookID: book_id,
csrfmiddlewaretoken: csrf // add csrf token to post data
},
success: function (response_data) {
alert('works fine')
},
error: function (response_data) {
console.log('error occurred');
}
});
});
});
</script>
{% csrf_token %} <!-- It will render a hidden input field with csrf token in it. Keep it outside for loop but in html. No need to render exactly same element multiple times. -->
{% for book in items_list %}
<div class="items">
<p class="title"> {{ book.book.title }}, quantity: {{ book.quantity }} </p>
<form method="post">
<input class="idInput" value="{{ book.book.id }}" > <!-- use class not id -->
<button class="remove" type="button"> Remove</button> <!-- you can use button type=button to avoid form submit and hence avoid event.preventDefault(); in js -->
</form>
</div>
{% endfor %}
I am working on a simple CRUD app using ember js. I have a template with a input form which sends data to the server and server responds with success response.
input form data: "user": {"id": 1, "name": "John"};
server response: {"message":"Created successfully", "nextId": 2}.
I want to display the success message on the same template(one with the input form). Because template refers to the user model and user model does not have a message attribute. How can it be done? Please help.
Here is my code:
var Manager = Ember.Application.create();
Manager.Router.map(function() {
this.resource('users');
this.resource('user', {path: '/users/:user_id'});
this.resource('home', {path: '/'});
});
Manager.UserRoute = Ember.Route.extend({
model: function(params) {
return jQuery.getJSON("http://localhost:8085/users/"+ params.user_id);
},
actions :{
insert : function(){
var user = this.modelFor("User");
$.ajax({
url: "http://localhost:8085/Users",
data: JSON.stringify(user),
type: "POST",
contentType: "application/json",
})
.done(function(data){
//set data.message to display on UI
})
}
}
});
and my template looks like this:
<script type="text/x-handlebars" data-template-name="user">
<form class="form-horizontal" role="form" {{action "insert" on="submit"}}>
<div class="form-group">
<label for="userId" class="control-label col-xs-2">User Id</label>
<div class="col-xs-4 input-group">
{{input type="number" value=_id class="form-control" id="userId" placeholder="Identity"}}
</div>
</div>
<div class="form-group">
<label for="name" class="control-label col-xs-2">Name</label>
<div class="col-xs-4 input-group">
{{input type="text" value=name class="form-control" id="name" placeholder="Name"}}
</div>
</div>
{{#if message}}
<div class="alert alert-success input-group" role="alert">{{message}}</div>
{{/if}}
<div class="form-group button-center">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</script>
Set the message property on your controller to the response that comes back.
actions :{
insert : function(){
var user = this.modelFor("User");
var self = this;
$.ajax({
url: "http://localhost:8085/Users",
data: JSON.stringify(user),
type: "POST",
contentType: "application/json",
})
.done(function(data){
//set data.message to display on UI
self.controllerFor('user').set('message', data.message);
})
}
}
I am using Django 1.5 and Dojo 1.8. I am trying to get Dojo to submit a form back to a Django view when I click a button.
Here is my Django view:
def report(request, report_id, report_url=None, template='report_parameters.html'):
if request.method == 'POST':
form = ReportParametersForm(request.POST)
if form.is_valid():
report_params = form.save()
html = "Success!"
return HttpResponse(html)
else:
form = ReportParametersForm()
return render(request,template, {
'form': form,
'report_url': report_url,
'report_id': report_id,
})
Here is the html page:
<div id="report_body">
<form data-dojo-type="dijit/form/Form" id="parameters_form" data-dojo-id="parameters_form">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<p><button id="submit_parameters" dojoType="dijit.form.Button" type="submit">Submit</button></p>
</form>
</div>
<script type="dojo/on" data-dojo-event="submit" data-dojo-args="e">
e.preventDefault();
require(["dojo/dom", "dojo/request", "dojo/dom-form"], function(dom, request, domForm){
on(dom.byId("submit_parameters"), "click", function() {
console.log("Dojo Post");
request.xhr("/report_parameters/report_id/report_url/", {
method: "post",
handleAs: "json",
data: domForm.toJson("parameters_form"),
}).then(
function(response){
alert(response);
dom.byId("report_body").innerHTML = "Report!";
},
function(error){
dom.byId("report_body").innerHTML = "<div class=\"error\">"+error+"<div>";
}
);
});
});
</script>
When I click the Submit button, I want to send a POST request to the url passing the data I have in my form. However, right now when I click Submit, the page reloads with a url looking something like this: /?csrfmiddlewaretoken=Y9gaNMFRWZNXMbJ2L3Ev7A5iKPGTuWeF¶m_1=0¶m2=0/report_parameters/report_id/report_url/.
I don't see the Dojo Post that should be appearing in my console.
How do I get my form to submit?
This fiddle seems to do what you want.
The major differences seem to be:
The <form> is actually a <div>. The Dojo documentation for Form links to reasons why this is done for IE.
All the related event script is inside the form <div>.
Remove the on(dom.byId("submit_parameters")... code, as there's already a declarative submit event handler.
HTML code:
<div id="report_body"></div>
<div data-dojo-type="dijit/form/Form" id="parameters_form" data-dojo-id="parameters_form" encType="multipart/form-data" action="" method="">
<input name="dummy" value="dummy">
<script type="dojo/on" data-dojo-event="submit" data-dojo-args="e">
console.log("submit");
e.preventDefault();
require(["dojo/dom", "dojo/request/xhr", "dojo/dom-form"], function(dom, xhr, domForm) {
console.log("Dojo Post");
var url = "/report_parameters/report_id/report_url/";
var data = domForm.toJson("parameters_form");
// overwrite url and data for jsfiddle
url = "/echo/json/";
data = {
json: data
};
xhr(url, {
method: "post",
handleAs: "json",
data: data,
}).then(function(response) {
alert(JSON.stringify(response, null, 2));
dom.byId("report_body").innerHTML = "Report!";
}, function(error) {
dom.byId("report_body").innerHTML = "<div class=\"error\">" + error + "<div>";
});
});
</script>
<button data-dojo-type="dijit/form/Button" id="submit_button" type="submit" name="submitButton" value="Submit">Submit</button>
</div>
JS code:
require(["dojo/parser", "dijit/registry", "dijit/form/Form", "dijit/form/Button", "dijit/form/ValidationTextBox", "dijit/form/DateTextBox", "dojo/domReady!"], function (parser, registry) {
parser.parse().then(function () {
console.log("parsed");
console.log(registry.byId("parameters_form"));
console.log(registry.byId("submit_button"));
});
});
I had to modify the above slightly. This is what eventually worked for me:
<div id="report_body"></div>
<form data-dojo-type="dijit/form/Form" id="parameters_form" data-dojo-id="parameters_form" encType="multipart/form-data" action="" method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<script type="dojo/on" data-dojo-event="submit" data-dojo-args="e">
e.preventDefault();
require(["dojo/dom", "dojo/request/xhr", "dojo/dom-form"], function(dom, xhr, domForm){
var url = "/report_parameters/report_id/report_url/"
var data = domForm.toObject("parameters_form")
xhr(url, {
method: "post",
data: data,
}).then(
function(response){
alert(response);
dom.byId("report_body").innerHTML = "Report!";
},
function(error){
dom.byId("report_body").innerHTML = error;
}
);
});
</script>
<p><button id="submit_parameters" dojoType="dijit/form/Button" type="submit" name="submitButton" value="Submit">Submit</button></p>
</form>
Using either the <div> or <form> tags to wrap the whole thing worked for me.