I have a form and post it to server using json data,and the server save it in database. here is my code
function saveChanges() {
var items = [];
$('ol.item_list > li.item').each(function(){
items.push(getItemData($(this)));
});
var csrftoken = $.cookie('csrftoken');
$.ajax({
url : '',
type: 'POST',
headers : {"X-CSRFToken": csrftoken},
data : $.toJSON(items),
success: function(data, textStatus, jqXHR){
console.log(data);
},
error: function(jqXHR, textStatus, errorThrown){
alert(textStatus);
},
});
}
The problem is, I call saveChanges (via a button) twice, all return 200 http ok. So I got duplicate data in database. Should the csrf token provent duplicate sumbit? How can I fix it?
You should prevent double submission by taking care to properly
lay out your script execution flow & script structure so that you prevent that.
No, the CSRF token doesn't prevent duplicate submit of any kind. Its purpose is to prevent Cross Site Request Forgery, nothing else. It creates a token so nobody can trick you in submitting requests you don't intend to do.
If you want to prevent duplicate submits, a way would be to disable the submit button after it is clicked once. However, this is by no means a good solution, since JavaScript runs on client side and can easily be manipulated (e.g. via Firebug). So duplicate submits would still be possible, just not that obviously.
A better way is to do validation in your server-side Python code. You can check if the submitted data is already in the database and, if so, ignore the request or optionally return an error message. This makes sure that even by fiddling around with the JavaScript, an evil-meaning user cannot save data twice.
I would use both of these means, the first one simply to tell the user that he should not try to submit the same data twice - that's just an interface perk.
Related
I am building an express project, using ejs as a view engine, and AJAX for front-end http calls.
When I post a request such this:
$.ajax({
type: 'POST',
data: {'nickname' : $('#nickname').val()},
contentType: 'application/x-www-form-urlencoded',
url: 'http://localhost:5000/create',
success: function(data) {
$('#message').text("Unkwon error");
},
error: function(data){
$('#message').text('Something went wrong, check connection!');
}
The Ajax keeps waiting for a response, which I am not willing to give, as I just want to render a view as follows :
app.post('/create', urlencodedParser, (req, res)=>{
let code = unique.generate(rooms);
res.render('chat', {'nickname' : req.body.nickname, 'code' : code}
Any ideas how can I work around this?
After some research, I found a way to do it.
Basically, I can just tell the Ajax to attach the document sent from rendering to the html body
$('body').html(data);
Surprisingly, this works event with Ejs dynamic tags.
I know it's not the best way to do it, but it's the only one I found till now.
EDIT 1:
After few months, I realized the solution is simple as just changing the Location using javascript
window.location.replace(`http://localhost:5000/newRequest`);
Now, I could handle this new request separately on the server.
EDIT 2:
After couple years now, I realized a GET request might have solved the problem in a single round trip.
It's my first time using AJAX and I don't understand why I need to specify url parameter in a JS Ajax call.
{% block javascript %}
<script>
$("#id_username").change(function () {
$.ajax({
url: '/some_new_url/',
data: {
'something': ...
},
success: function (data) {
if (data.is_taken) {
alert("Data is already in DB");
}
}
});
});
</script>
{% endblock %}
To my understanding, AJAX is used to do something on the server side without refreshing a page. So it shouldn't redirect to a new url upon sending a data to the server, and stay on the same url. And yet AJAX call requires url parameter.
And I don' really like this, because setting a new url means I have to add another url pattern in my app/urls.py.
re_path(r'^create/$', views.Some_View.as_view(), name='create'),
And as a consequence, make another view in my views.py
class Some_View(ListView):
model = SomeModel
fields = '__all__'
But, I already have a CBV that generates form fields on the user side and accepts user inputs. I only want to make my existing CBV to save data to DB using AJAX call.
Since I don't understand what the purpose of the url is, I don't know how to set up my new url pattern, and CBV. Can I get some explanation here?
++ This is just a bonus question, but my ultimate goal is to generate multiple form fields, and multiple Submit buttons that sends the respective form input data to the server using AJAX. If there's any advice on how to tweak AJAX code, I would appreciate it.
An AJAX request is just a regular HTTP request to a url on the server. The only difference between an AJAX request and a request made by an ordinary browser GET or POST is that with AJAX, the results that come back from the server are returned to your javascript function and then you get to decide what to do with those results.
So there's no automatic updating of anything.
If you want to save something on the server, you need a view there on the server which is capable of understanding the data you are sending in the AJAX request, saving it, and then sending back a response which, again, your javascript code needs to be able to understand.
But if you already have a view which is capable of doing what you want, you can use it for your AJAX request, you just have to send a request with everything in it that the view requires.
Hopefully that title isn't too cryptic. What's happening is I have a jQuery AJAX script that I'm trying to use to access an API on a remote server, which returns a JSON response. However, the API returns the JSON as MIME type "text/html" (in the response header) instead of "application/json". It would seem obvious that I simply need to change the returned content type from text to JSON, to make the AJAX call interpret the data correctly.
Unfortunately, this is not the case. I have tried this in a multitude of different ways, all of which fail. The closest I've gotten to getting this API call to work is when the debugger tells me "Resource interpreted as Script but transferred with MIME type text/html". And the AJAX call errors out with my debug message that dumps the jqXHR object in JSON format, which tells me: {"readyState":4,"status":200,"statusText":"parsererror"}
Here is an example of my code (although I have changed the code many various ways, in my attempts at getting it to work, but this version seems to be the closest to correct):
$.ajax({
type: 'GET',
url: 'http://username:api-key#www.kanbanpad.com/api/v1/projects.json',
contentType: 'application/json',
dataType: 'jsonp',
converters: {
'jsonp': jQuery.parseJSON,
},
success: function(data) {
alert(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(JSON.stringify(jqXHR));
console.log(textStatus+': '+errorThrown);
}
});
If anyone can figure out what I need to do differently to make this work, I will be extremely grateful.
It may also be worth noting that if you copy/paste the API URL into a browser address bar and hit go, it gives the proper JSON response with the proper response header ("application/json")
So unless Kanbanpad updates their API, it cannot be directly accessed with JS. You will have to use PHP (or some other) to handle the requests.
It works just as well, it just requires an extra step is all.
Just for anyone that was looking for a solution.
dataFilter(data, type)Function
A function to be used to handle the raw response data of XMLHttpRequest.
This is a pre-filtering
function to sanitize the response. You should return the sanitized data. The function
accepts two arguments: The raw data returned from the server and the 'dataType' parameter.
I would change the content type in the dataFilter interceptor to json. Bear in mind this affects all ajax calls, so use info from data to decide which ones you want to convert.
Verify that your server is sending a jsonp response. This means the json should be enclosed with a string of your callback.
The callback name is passed in the parameters, and if you're not setting it explicitly, looks something like: jQuery15102810791094068532_1300988427891 (As per http://www.json-p.org/)
On your server, you need to format the response:
jQuery15102810791094068532_1300988427891({...json response ...});
Where you use the callback defined in your GET parameter 'callback'.
You might try setting the type to "json" and see if it works. I've had a number of parsererror's with the jquery's jsonp - you might try http://code.google.com/p/jquery-jsonp until it's a bit smoother.
Try changing your content-type to this
contentType: "application/json; charset=utf-8",
I am trying to test Jquery ajax calls in Firefox but it it not working. I mean my server is not receiving any requests. But when I test in IE8 it works fine. Here is my ajax call:
$("#getWeatherReport").click(function(){
$cityName = "New York";
$.ajax({
type: "POST",
dataType:"xml",
url: "http://localhost:8080/Test/WeatherServlet",
data: "cityName="+$cityName,
success: function(data) {
alert($("report", data).text());
},
error: function(xhr, textStatus, errorThrown) {
alert('ERROR['+xhr.statusText+']');
}
});
});
It is not even calling error function. And from my server code(java) I am setting content type as "text/xml".
Any suggestions?
Your string is not correctly serialized, I'm not sure if that's the issue, but it may be and it's definitely a potential one for later, try this for an immediate test:
var $cityName = "New+York";
As a more permanent solution, pass data as an object, like this:
data: {cityName: $cityName},
Have you installed Firebug?
Your best bet would be to install Firebug, which comes with a console that'll notify you of any javascript errors. You can also use it (via the "Net" tab) to monitor all requests made by your page.
From what I can see, your code looks OK (other than the possible issue pointed out by #Nick Craver)
Also, why the '$' on your cityName variable? The '$' prefix in Javascript is meant to be reserved for machine-generated code (so that it has no chance of conflicting with user code).
try installing firebug plugin in ff :: https://addons.mozilla.org/en-US/firefox/addon/1843/
Then check the :::: Net Tab >> All selected
Refresh the page and see is your ajax call actually getting called. If yes is there any syntax error in the call or any variable null error. If all is fine then you can think of further issues
Usually, when I end up with a parseerror that means that the return header type is wrong or that somehow the server sent extra data with the response. For instance, if I'm looking to get JSON back and I get the JSON and some HTML from x-debug.
Also, The OPTIONS request is for cross-domain requests which is what #Nick was alluding to.
A helpful link to get you started.
I am performing the following AJAX call:
$(document).ready(function() {
$.getJSON('https://sendgrid.com/api/user.stats.json',
{
'api_user': 'me#mydomain.com',
'api_key': 'MYAPIKEY',
'user': 'me#mydomain.com',
'category': 'MY_CATEGORY'
},
function(response){
alert('received response');
}
);
});
and I get no alert message as expected. Instead, Firebug says I get "501 Not Implemented."
Why? What do I need to do to fix this?
If I go to the URL corresponding to the AJAX call in Firebug, I get a JSON file as a download, and it contains the expected data.
One thing I've noticed is that firebug says OPTIONS instead of GET:
alt text http://grab.by/grabs/b1a13d92a4fc69aa310880a5d7a06b95.png
I don't know if this is related, but generally when requesting JSON on the client to a server in a different domain you'll need to use JSONP instead of JSON due to the Same Origin Policy. Unfortunately, it doesn't appear that their API supports using JSONP -- so they must expect you to interact with their site from your server. In that case you'll need proxy methods on your server to translate the calls to their API so that the client calls are made to a server in the same domain as the page.
As this is the top Google match for "jQuery 501 (Method not implement)" I thought I'd share what worked for me when experiencing this on the same domain (which is not your problem).
My problem was that I was not returning valid JSON, I was just returning "1". So to fix this, either:
Ensure you return valid JSON, or if you don't require a JSON response,
Swap your call to use $.ajax instead of $.getJSON, or
If you're already using &.ajax, remove type: "json"
Hope that helps some people.
I had the same problem, and realized it was an encoding problem. It was solved by encoding the values of the data sent to the server. Try something like:
$(document).ready(function() {
$.getJSON('https://sendgrid.com/api/user.stats.json',
{
'api_user': encodeURIComponent('me#mydomain.com'),
'api_key': encodeURIComponent('MYAPIKEY'),
'user': encodeURIComponent('me#mydomain.com'),
'category': encodeURIComponent('MY_CATEGORY')
},
function(response){
alert('received response');
}
);
});
end then decode the data on backend. Hope it helps someone.