Portable way of making an ajax request from JS code - django

This is probably a silly question, but I can't find an obvious response.
I'm developing a web application using (Geo)Django for the backend and Leaflet, among others, for the frontend. My point is I want to make a url call from my JS code to my Django backend. Something like this:
$.ajax({
type: 'POST',
url: '<A_URL_HERE>',
data: {"data":<MY_JSON_DATA>},
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
console.log("Data saved");
},
error: function (responseData, textStatus, errorThrown) {
console.log("Problem saving the data");
}
});
My problem is with the url. I know that cool URIs don't change, but for example, if I want to keep different dev/test/prod environments without changing that parameter, how should I do it? In the backend part, I'm following good practices for this kind of problems, but I have short experience with JS and frontend.
Many thanks in advance

Two possible solutions:
Use dynamically generated JavaScript, i.e. the JavaScript file is not a hardcoded static file. Instead it is a template which backend populates with variables (in particular URL);
Similar to the one above except that JavaScript is a hardcoded static file and for example you put your URLs in base HTML (which is generated from a template on the server side):
base.html
<script>window.urls = { "my_url": "{{ my_url }}" };</script>
my_script.js
$.ajax({
url: window.urls.my_url,
...
});
With this you can generate URLs based on you server settings.

Related

(Opencart) How to load a controller in a function and not break ajax with that function?

Is there a way to load controller (product/category) within some contained space, so that the ajax to the custom function within that controller doesn't break?
I'm basically loading (from ajax) a custom function which is inside a core contoller product/category. In this function I need to reload the the product/category controller to get new product list based on ajax data I sent to the function, to then return it as a response to the original ajax.
When I try to do
$this->load->controller('product/category')
it beaks the ajax I set up with the function and in the console I see 404.
I tried using
$foo = $this->load->controller('product/category')
and it works, but I need to also execute
$this->load->view('product/category')
and I don't know how to do it without breaking ajax.
Basically I did what I essentially wanted (see the middle of my question, namely the part about the ultimate need to refresh my product list using ajax) the other way (after reading up How to get products in JSON format from OpenCart using phonegap/jQueryMobile): from the ajax I called the products/category directly and not my custom function inside of the product/category controller as in the question, and when I got reponse back containing the html output of the view, I reloaded a div I made in the product/category.twig with that html using jQuery. The ajax was
$(document).ready(function(){
$.ajax({
url: 'index.php?route=product/category&path=18&json',
type: 'get',
beforeSend: function() {
},
complete: function() {
},
success: function(data) {
console.log('success');
if (data.length > 0) {
console.log(data);
$('#mydiv').html(data);
}
}
});
});
and the code I added to product/category.php was
if(isset($this->request->get['json'])) {
$this->response->setOutput($this->load->view('product/view_for_mydiv', $data));
} else {
$this->response->setOutput($this->load->view('product/category', $data));
}
As you may notice I added a div inside product/category.twig called mydiv, which I placed exactly where I wanted the html to go and then I created a twig called view_for_mydiv.twig inside default/product/category/ folder, the html of which the product/category controller would send back instead of its general twig when it saw that an ajax call had been made to it. The #mydiv div located inside category.twig wraps the html that is the same html that gets produced when view_for_mydiv.twig is used to render product/category.

How to handle multiple actions in Django-Template

I have created a web app in which page which consist of choose file input and Now I need to preprocess the data with one button and that preprocessed data should be used for next button called forecast to show the result in that page.Is it possible with Django.
Does it compulsory to take any action in page with url changes in django?
The question is not completely clear, but from what I understand you can use Ajax. On first button click send an ajax request, process it in the view logic, send the appropriate data using maybe JsonResponse, and in the success block of your ajax request set the appropriate data for your forecast button using jquery. Something like -
$.ajax({
url: <url_of_data_processing_logic>,
type: 'post',
data: <required data>,
dataType: 'json',
success: function (data) {
$("#<forecast_button_Id>").html(data.forecast_html);
},
error: function (e) {
console.log(e);
}
});

csrf_token of Django into Vuejs when seperate them

I am using ajax request to send POST but it got response 403 because of csrf_token. I divide the frontend just using Vuejs and backend using Django to just reponse API only so I can't use Django template to render {% csrf_token %} or having csrftoken in session to use getcookie('csrftoken') like in Django's doc recommend. Is there anybody face this problem like me and got some solutions ? So thank you if you can help me this.
You can set the CSRF token in the header of your AJAX request. E.g., if you use jquery and jquery.cookie library, you can easily retrieve the Django-set csrftoken cookie like so:
$.ajax({
url : 'YOUR_URL_HERE',
headers: {'X-CSRFToken': $.cookie('csrftoken')},
type: 'POST',
dataType: 'json',
data: {},
success: function() {
},
error: function(xhr, errMsg, err) {
},
});
Django documentation also includes a section on this: https://docs.djangoproject.com/en/1.11/ref/csrf/#ajax
Please note that this solution may depend on your specific Django settings. The Django documentation link above details everything pretty clearly.
EDIT:
Given that even your initial page request is not served by Django, here is how you can accomplish what you're looking for...
1.) Create a view in your Django app that manually generates and returns a CSRF token (using django.middleware.csrf.get_token):
def get_csrf_token(request):
token = django.middleware.csrf.get_token(request)
return JsonResponse({'token': token})
2.) You would also need to add an appropriate entry in your Django URLs file:
url(r'^get-token/$', get_csrf_token)
3.) Then your Vue.js app can fetch the CSRF token using this endpoint. This doesn't need to be a user-initiated event; for example, you can configure your front-end app to fetch it on the $(document).ready() event. Then, using your preferred AJAX library (I am using jQuery in my example):
$.ajax({
url: '/get-token/',
type: 'GET',
dataType: 'json',
success: function(data) {
$.cookie('csrftoken', data.token); // set the csrftoken cookie
}
});
4.) Now your csrftoken cookie is set and should be usable for subsequent POST requests.
$.ajax({
url : 'YOUR_URL_HERE',
headers: {'X-CSRFToken': $.cookie('csrftoken')},
type: 'POST',
dataType: 'json',
data: {},
success: function() {
},
error: function(xhr, errMsg, err) {
},
});
I have used jQuery for AJAX functionality and the jQuery.cookie library for getting and setting cookies, but of course you can use whichever library you would prefer for these functions.
According to the Django documentation you can simply use the ensure_csrf_cookie decorator on a view and that will send the cookie with the token with the response.
This is going to be wildly unpopular, but I've found it to be a relatively simple, secure and unobtrusive way to separate the front/backend.
In your VueJS app, you've probably got a login redirect when the user tries to access a page and are unauthenticated.
So instead of sending it to a vue router page, redirect it to /account/login/ (or some django app route - put an exception in cloudfront, or nginx proxy for /account/login/ to proxy pass to django) - then in the login.html template, just use a javascript window.location.href to your vueJS login page /login
The csrf_token will be set as a HttpOnly, secure cookie (which is what you want), and the disruption to the user is so minimal as to not even justify worrying about.

Using jquery $.get to call an external web service

I am calling the following jQuery code on page load to test the concept of calling an external web service from the client. The data object in the success callback is always empty. What am I doing wrong?
$.ajax({
url: "http://www.google.com/search",
type: 'GET',
data: { q: "green tea" },
success: function(data) { alert("Data Loaded: " + data) },
dataType: "text/html"
});
It's the same-origin policy you're hitting here, it's specifically in place to prevent cross-domain calls for security reasons. The expected behavior is for the response to be empty here.
You either need to fetch the data via JSONP or get the data via your own domain, your server proxying the request.
It's worth noting Google has a full JavaScript API for searching that you may want to check out for doing this.
browser dont allow you to make cross domain request(a security feature). there is a hack for that with a limitation that you can get only json as response.
----the trick (hack)----
using jquery(or javascript)you create a new script tag and with src="url_of_third_party?", when that request is made you get json from cross site.
jQuery('body').append('<script src="cross_site_url" type="text/javascript"></script>');
or simply you can do this
$.ajax({
url: "http://www.google.com/search",
type: 'GET',
data: { q: "green tea" },
success: function(data) { alert("Data Loaded: " + data) },
dataType: "jsonp",
});
note: dataType=jsonp

Calling a webservice from a subfolder

I'm using ASP.net and I'm trying to execute a webmethod from jquery. I have the following file structure:
/MyWebService.asmx
/MyPage1.aspx (referencing a javascript file which calls a webmethod in MyWebService.asmx)
/MySubFolder/MyPage2.aspx (MyPage2.aspx referencing the same javascript file)
My problem is that MyPage1.aspx can call the webmethod in the web service but MyPage2.aspx can't. Any ideas why? It has to be related to the fact that MyPage2.aspx is in a subfolder. If I simply move MyPage2.aspx to the root it works.
I'm using jquery and the code in the javascript file looks like this:
$.ajax({
type: "POST",
url: "MyWebService.asmx/MyWebMethod",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg)
etc.
I've tried changing the url to: /MyWebService.asmx/MyWebMethod (with a slash in front of MyWebService) but it doesn't make any difference.
Thanks.
I think it's worth a try to pass the relative URL such as "../MyWebService.asmx/MyWebMethod".
Personally, I prefer to pass absolute URL's during AJAX hits.