Django - AJAX - Why do I need url parameter? - ajax

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.

Related

Send object with axios get request [duplicate]

This question already has answers here:
Axios get in url works but with second parameter as object it doesn't
(4 answers)
Closed 5 years ago.
I want to send a get request with an object. The object data will be used on the server to update session data. But the object doesn't seem to be sent correctly, because if I try to send it back to print it out, I just get:
" N; "
I can do it with jQuery like this and it works:
$.get('/mysite/public/api/updatecart', { 'product': this.product }, data => {
console.log(data);
});
The object is sent back from server with laravel like this:
public function updateCart(Request $request){
return serialize($request->product);
The same thing doesn't work with axios:
axios.get('/api/updatecart', { 'product': this.product })
.then(response => {
console.log(response.data);
});
I set a default baseURL with axios so the url is different. It reaches the api endpoint correctly and the function returns what was sent in, which was apparently not the object. I only get "N; " as result.
Axios API is a bit different from the jQuery AJAX one. If you have to pass some params along with GET request, you need to use params property of config object (the second param of .get() method):
axios.get('/api/updatecart', {
params: {
product: this.product
}
}).then(...)
You can pass either a plain object or a URLSearchParams object as params value.
Note that here we're talking about params appended to URL (query params), which is explicitly mentioned in the documentation.
If you want to send something within request body with GET requests, params won't work - and neither will data, as it's only taken into account for PUT, POST, DELETE, and PATCH requests. There're several lengthy discussions about this feature, and here's the telling quote:
Unfortunately, this doesn't seem to be an axios problem. The problem
seems to lie on the http client implementation in the browser
javascript engine.
According to the documentation and the spec XMLHttpRequest ignores the
body of the request in case the method is GET. If you perform a
request in Chrome/Electron with XMLHttpRequest and you try to put a
json body in the send method this just gets ignored.
Using fetch which is the modern replacement for XMLHtppRequest also
seems to fail in Chrome/Electron.
Until it's fixed, the only option one has within a browser is to use POST/PUT requests when data just doesn't fit into that query string. Apparently, that option is only available if corresponding API can be modified.
However, the most prominent case of GET-with-body - ElasticSearch _search API - actually does support both GET and POST; the latter seems to be far less known fact than it should be. Here's the related SO discussion.

How to use NodeJS with node-rest-client methods to post dynamic data to front end HTML

I am rather new to NodeJS so hopefully I am able to articulate my question(s) properly. My goal is to create a NodeJS application that will use the node-rest-client to GET data and asynchronously display it in HTML on client side.
I have several node-rest-client methods created and currently I am calling my GET data operation when a user navigates to the /getdata page. The response is successfully logged to the console but I'm stumbling on the best method to dynamically populate this data in an HTML table on the /getdata page itself. I'd like to follow Node best practices, ensure durability under high user load and ultimately make sure I'm not coding a piece of junk.
How can I bind data returned from my Express routes to the HTML front end?
Should I use separate "router.get" routes for each node-rest-method?
How can I bind a GET request to a button and have it GET new data when clicked?
Should I consider using socket.io, angularjs and ajax to pipe data from the server side to client side?
-Thank you for reading.
This is an example of the route that is currently rendering the getdata page as well as calling my getDomains node-rest-client method. The page is rendering correct and the data returned by getDomains is successfully printed to the console, however I'm having trouble getting the data piped to the /getdata page.
router.get('/getdata', function(req, res) {
res.render('getdata', {title: 'This is the get data page'});
console.log("Rendering:: Starting post requirement");
args = {
headers:{"Cookie":req.session.qcsession,"Accept":"application/xml"},
};
qcclient.methods.getDomains(args, function(data, response){
var theProjectsSTRING = JSON.stringify(data);
var theProjectsJSON = JSON.parse(theProjectsSTRING);
console.log('Processing JSON.Stringify on DATA');
console.log(theProjectsSTRING);
console.log('Processing JSON.Parse on theProjectsSTRING');
console.log('');
console.log('Parsing the array ' + theProjectsJSON.Domains.Domain[0].$.Name );
});
});
I've started to experiment with creating several routes for my different node-rest-client methods that will use res.send to return the data and the perhaps I could bind an AJAX call or use angularjs to parse the data and display it to the user.
router.get('/domaindata', function(req, res){
var theProjectsSTRING;
var theProjectsJSON;
args = {
headers:{"Cookie": req.session.qcsession,"Accept":"application/xml"},
};
qcclient.methods.getDomains(args, function(data, response){
//console.log(data);
theProjectsSTRING = JSON.stringify(data);
theProjectsJSON = JSON.parse(theProjectsSTRING);
console.log('Processing JSON.Stringify on DATA');
console.log(theProjectsSTRING);
console.log('Processing JSON.Parse on theProjectsSTRING');
console.log('');
console.log('Parsing the array ' + theProjectsJSON.Domains.Domain[0].$.Name );
res.send(theProjectsSTRING);
});
});
I looked into your code. You are using res.render(..) and res.send(..). First of all you should understand the basic request-response cycle. Request object gives us the values passed from routes, and response will return values back after doing some kind of processing on request values. More particularly in express you will be using req.params and req.body if values are passed through the body of html.
So all response related statements(res.send(..),res.json(..), res.jsonp(..), res.render(..)) should be at the end of your function(req,res){...} where you have no other processing left to be done, otherwise you will get errors.
As per the modern web application development practices in javascript, frameworks such as Ruby on Rails, ExpressJS, Django, Play etc they all work as REST engine and front end routing logic is written in javascript. If you are using AngularJS then ngRoute and open source ui-router makes work really easy. If you look closely into some of the popular MEAN seed projects such as mean.io, mean.js even they use the ExpressJS as REST engine and AngularJS does the rest of heavyweight job in front end.
Very often you will be sending JSON data from backend so for that you can use res.json(..). To consume the data from your endpoints you can use angularjs ngResource service.
Let's take a simplest case, you have a GET /domaindata end point :
router.get('/domaindata',function(req,res){
..
..
res.json({somekey:'somevalue'});
});
In the front end you can access this using angularJS ngResource service :
var MyResource = $resource('/domaindata');
MyResource.query(function(results){
$scope.myValue = results;
//myValue variable is now bonded to the view.
});
I would suggest you to have a look into the ui-router for ui front end routing.
If you are looking for sample implementation then you can look into this project which i wrote sometime back, it can also give you an overview of implementing login, session management using JSON Web Token.
There are lot of things to understand, let me know if you need help in anything.

JSON or Form Data? What's the preferred way to send data back to the server

I'm messing around with Django and AngularJS, attempting to send data back to my server using the $http resource. It looks like I could do this by either posting the data back as a form by setting the content-type as follows:
$http({
url: url,
data: form_encoded_data,
method: 'POST',
headers : {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}
});
Or post back JSON in the request body with something like this:
$http.post(url, json_data)
.success(function(data, status, headers, config) {
...
}
In the first method, I can get access to the form data in my Django view via request.POST, and in the second, I can get access to the JSON via request.body. They both seem to work, but what's considered best practice?
I'm not sure what the convention for JSON data is. What I am sure of is that there is a convention for getting form data. In the absence of a compelling reason to use JSON, I would tend to think it's better to stick with the request.POST
I would go with using a form, it just makes sense intuitively and it is what I have used every time.
I prefer to use the $http service that accepts an object literal for configuration:
$http({method:'POST',url:'api/customers/add', data: customer})
.success(function(data) {
...
});
The result is promise object where you can immediately call .success. Its cleaner and easier to read IMO.
Note: customer is typically a data-bound object literal in JSON notation, but it does not have to be.

How to get a HTTPRequest JSON response without using any kind of template?

I am new to Django but i am advanced programmer in other frameworks.
What i intend to do:
Press a form button, triggering Javascript that fires a Ajax request which is processed by a Django View (creates a file) that return plain simple JSON data (the name of the file) - and that is appended as a link to a DOM-Element named 'downloads'.
What i achieved so far instead:
Press the button, triggering js that fires a ajax request which is process by a Django view (creates a file) that return the whole page appended as a duplicate to the DOM-Element named 'downloads' (instead of simple JSON data).
here is the extracted code from the corresponding Django view:
context = {
'filename': filename
}
data['filename'] = render_to_string(current_app+'/json_download_link.html', context)
return HttpResponse(json.dumps(data), content_type="application/json")
I tried several variants (like https://stackoverflow.com/a/2428119/850547), with and without RequestContext object; different rendering strats.. i am out of ideas now..
It seems to me that there is NO possibility to make ajax requests without using a template in the response.. :-/ (but i hope i am wrong)
But even then: Why is Django return the main template (with full DOM) that i have NOT passed to the context...
I just want JSON data - not more!
I hope my problem is understandable... if you need more informations let me know and i will add them.
EDIT:
for the upcoming questions - json_download_link.html looks like this:
Download
But i don't even want to use that!
corresponding jquery:
$.post(url, form_data)
.done(function(result){
$('#downloads').append(' Download CSV')
})
I don't understand your question. Of course you can make an Ajax request without using a template. If you don't want to use a template, don't use a template. If you just want to return JSON, then do that.
Without having any details of what's going wrong, I would imagine that your Ajax request is not hitting the view you think it is, but is going to the original full-page view. Try adding some logging in the view to see what's going on.
There is no need to return the full template. You can return parts of template and render/append them at the frontend.
A template can be as small as you want. For example this is a template:
name.html
<p>My name is {{name}}</p>
You can return only this template with json.dumps() and append it on the front end.
What is your json_download_link.html?
assuming example.csv is string
data ={}
data['filename'] = u'example.csv'
return HttpResponse(simplejson.dumps(data), content_type="application/json")
Is this what you are looking for?

How do I prevent tampering with AJAX process page?

I am using Ajax for processing with JQUERY. The Data_string is sent to my process.php page, where it is saved.
Issue: right now anyone can directly type example.com/process.php to access my process page, or type example.com/process.php/var1=foo1&var2=foo2 to emulate a form submission. How do I prevent this from happening?
Also, in the Ajax code I specified POST. What is the difference here between POST and GET?
First of all submit your AJAX form via POST and on a server side make sure that request come within same domain and is called via AJAX.
I have couple of functions in my library for this task
function valid_referer()
{
if(isset($_SERVER['HTTP_REFERER']))
return parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) == $_SERVER['SERVER_NAME'];
else
return false;
}
function is_ajax()
{
$key = 'HTTP_X_REQUESTED_WITH';
return isset($_SERVER[$key]) && strtolower($_SERVER[$key]) == 'xmlhttprequest';
}
You might read this post regarding difference between post and get
While as Jason LeBrun says it is pretty much impossible to prevent people simulating a form submission, you can at least stop the casual attempts to. Along with implementing Nazariy's suggestions (which are both easy to get round if you really want to), you could also generate some unique value on the server side (i'll call it a token), which gets inserted into the same page as your Ajax. The Ajax would would then pass this token in with your other arguments to the process.php page whereupon you can check this token is valid.
UPDATE
see this question with regards to the token
anti-CSRF token and Javascript
You can not prevent people from manually emulating the submission of form data on your website. You can make it arbitrarily more difficult, but you won't be able to prevent it completely.

Resources