URL sent to Django using AJAX is different when printed from Django - python

I have a JQuery event that, when a link is clicked, an AJAX POST request is sent to a Django function. There I print the recieved url and do other stuff with it. However, when it is printed (by Django) some characters in the url are changed.
The specific url this happened with was :
https://www.catholicleague.org/05press_releases/quarter%204/051110_put_on_notice.htm
Which was printed as :
https://www.catholicleague.org/05press_releases/quarter+4/051110_put_on_notice.htm
Where %20 was changed to +
Here is the AJAX and Django code:
$("a").on("click", function(e){
e.preventDefault();
if(e.target.href){
let clicked_source = e.target.href;
let csrf_tok = parent.document.getElementById("csrf_tok").value;
$.ajax({
url: "/change_origin/",
data: JSON.stringify({"clicked_source":clicked_source}),
type: "POST",
beforeSend: function (xhr, settings) { xhr.setRequestHeader("X-CSRFToken", csrf_tok );},
success: function(response) {
console.log(response.msg)
},
error:function(error) { console.log(error); }
});
}
});
def change_origin(request):
if request.method == 'POST':
received = ast.literal_eval(request.body.decode())
print(received)
clicked_source_url = received['clicked_source']
return JsonResponse({'msg': "ok"})
Where decode is used as the JSON object is received in Python as a byte-like object. And ast is used to turn the string representation of the object to an actual object (or dict) for access.
I need either:
1) A way to just send a string from Ajax to Django
2) A better way to deal with the received object as I believe using .decode() might be the one causing this issue.
EDIT: The link is the second link in the "origin" part of this article
https://www.snopes.com/fact-check/an-unmerried-woman/

Related

Returning two arrays from a python script in Django and utilizing in Ajax simultaneously

I have a python script running in views.py within Django which returns two very large string arrays, x and y. It currently is able to run off a button press within my index.html.
def python_file(request):
final()
return HttpResponse("ran")
The ajax code I have running to do the button press.
<script src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script>
function gotoPython(){
$.ajax({
url: "/python_file",
context: document.body
}).done(function() {
alert('finished python script');
});
}
</script>
It's also attached to the URLS.py. I know there's no array being returned right now, because I am unsure how to run the script, get the data simultaneously, then add it to the page without refreshing the page. So, I am asking what would be the best practice to do what I described. Any help would be appreciated.
This is generally what I do, not sure if it's best practice, but I return it with Json
I included two examples, and POST and a GET.
I also included some other stuff I usually return status and msg. When I catch an error or have an invalid POST I send back status = False and msg = '{error message}, then I can show that error message in the front end with Javascript. I keep this standardized in my project, but you do you.
def python_file(request):
xArray, yArray = final()
import json
data = {
'status': True, # True=All Good. False=Caught Error but didn't crash.
'x': xArray,
'y': yArray,
'msg': 'returning x and y arrays',
}
return HttpResponse(
json.dumps(data),
content_type="application/json"
)
function gotoPython(){
$.ajax({
method: 'GET',
url: '/python_file',
success: function(data){
console.log(data)
if (data['status']){
// do things with arrays
data['x']
data['y']
}else{
console.log('Server Replied with Error, but did not Crash');
console.log(data['msg']);
};
},
error: function(event,xhr,settings,errorText){
// general `xhr.status` Key for common errors
// 0 = Server didn't Reply (Server Down)
// 400 = Bad Request (Syntax Error)
// 403 = Forbidden (Login Token Expired or not in Group)
// 403 = Not Found (Invalid Url)
// 500 = Server Error (Django Crash)
},
});
};
function gotoPythonWithData(){
// if you wanted to POST data to this function you'd just do
// Note: Requires csrfmiddlewaretoken in template
// Throw this anywhere (it's hidden): {% csrf_token %}
submitData = {
'return_item_count': 25,
'csrfmiddlewaretoken': $('[name=\'csrfmiddlewaretoken\']').val(),
};
$.ajax({
method: 'POST',
url: '/python_file',
data: submitData,
success: function(data){
if (data['status']{
// do stuff
}else{
console.log(data['msg']);
};
},
error: function(event,xhr,settings,errorText){
},
});
};
Note: Some things like, Django Decimal objects, can not be be put into a Json Dump. In the Decimal example you've got to turn them into a Float or an Int
You can add parameters to the ajax.done(function) in order to get what your server returned.
$.ajax({
url: "/python_file",
context: document.body
}).done(function (response, textStatus, jqXHR) {
// What happens when the call is successful (200 <= status code < 300
console.log(response); // Logs what you returned from your django
// x + "separator" + y
})
.fail(function (jqXHR, textStatus, errorThrown) {
// Status code over 400
})
.always(function (jqXHR, textStatus, errorThrown) {
// Always happens
...
});
You can check ajax documentation here : https://api.jquery.com/jquery.ajax/#jQuery-ajax-settings-settings
And your django view should return some text content :
def view(response):
// code
return HttpResponse(status=200, content=x + "separator" + y)

Asynchronously update page with data that are stored by middleware

I have middleware, that stores all http requests into DB.
Also I have view, that fetches data from DB and put this data into the context.
views.py
def requests(request):
http_requests = WebRequest.objects.all()
context = {
"http_requests": http_requests
}
return render(request, "requests.html", context)
How can I asynchronously update data on this page as new requests come in (so, new requests should appear on this page asynchronously)? Can I use only Django features to achieve such behavior or I need to use some javascript libraries?
It depends on how much time you want to spend on the project. As Lorenzo stated, it might make sense to create an API and have javascript-frameworks (e.g. emberjs or angularjs) handle the asynchronity. I dont think you can handle this with pure django...
If you don't have time and are in for some 'hack' you could just replace the content of your page by polling the url and replacing the whole document with the response:
$.ajax({
type: "GET",
url: "<url_to_your_requests_view>",
success: function(response){
$('body').html(response);
}
});
This is NOT clean, but should work as a quick an dirty trick...
EDIT: If you only want to exchange certain parts of your site, you can break it down to just add elements to the page:
$.ajax({
type: "GET",
url: "<url_to_your_requests_view>",
success: function(response){
var newlyAddedRows = // find your newly added rows through some jquery
newlyAddedRows.forEach(function(row){
$('#request-holder').append(row);
});
}
});
OR WITH JSON
$.ajax({
type: "GET",
url: "<url_to_your_requests_api_endpoint>",
success: function(response){
var requestRows = response.requestItems
var $requestsHolder = $('#request-holder');
$requestHolder.empty();
requestRows.forEach(function(row){
requestsHolder.append('<div class="request-row">' + <visualize your data somehow> + '</div>'); //e.g. row.timestamp if you have that in your json
});
}
});

How to send back data to Chrome Extension from webapp2?

I have a Chrome Extension which sends data to Google App Engine(webapp2).
chrome.extension.onMessage.addListener(function (message, sender, sendResponse) {
if (message.paragraphs_ready) {
$.ajax({
url: 'http://my_website.appspot.com/',
type: 'POST',
data: {'paragraphs_ready': message.paragraphs_ready},
contentType: "application/x-www-form-urlencoded",
//dataType: 'json',
success: function(){
alert("Server received my data");
}
});
}
});
GAE(webapp2) processes data and should send a response back to Chrome Extension. I don't want to go for Channel Python API if possible.
class DataProcessing(webapp2.RequestHandler):
"""This Handler is responsible for the Processing"""
def post(self):
to_be_processed = cgi.escape(self.request.POST['paragraphs_ready'])
def my_proc(to_be_processed):
return to_be_processed
self.response.write(my_proc(to_be_processed)
success function on ajax request is called when the server responds not when the client sends a request.
So in your case you would have something like this:
success: function(data){
alert("Server received my data AND sent a response");
alert(data);
}
success: A function to be called if the request succeeds. The function
gets passed three arguments: The data returned from the server,
formatted according to the dataType parameter; a string describing the
status; and the jqXHR (in jQuery 1.4.x, XMLHttpRequest) object. As of
jQuery 1.5, the success setting can accept an array of functions. Each
function will be called in turn.
See more here: http://api.jquery.com/jquery.ajax/

how to open a PDF file while returning the file in AJAX request success response

I get 2 dates, start and end date, via AJAX. I process the data b/w those 2 dates, generate a report and then returns an HttpResponse. The PDF report is now saved in my main project directory. Now I get a response back in AJAX. So, now how should I process the response in the success function, sent back from the sever and open a PDF file.
Thanks.
jQuery
$(function() {
$("#report_submit").click(function(){
$.ajax({
type : "POST",
url: "/reports/",
data : { 'start_date' : $("#startDate").val() , 'end_date' : $("#endDate").val() },
success : function(result){
},
error : function(result){
}
});
});
});
Django view code
def generate_report(request):
ctx = {}
if request.is_ajax():
if request.POST.has_key('start_date'):
start_date = datetime.strptime(request.POST[ 'start_date'] , '%m/%d/%Y')
end_date = datetime.strptime(request.POST[ 'end_date'] , '%m/%d/%Y')
......
# PDF GENERATED in MAIN PROJECT DIRECTORY
with open(os.path.join(os.path.dirname(__file__),'../../../../gui','Report.pdf')) as pdf:
response = HttpResponse(pdf.read(), content_type='application/pdf')
response['Content-Disposition'] = 'inline;filename=Report.pdf'
return response # so, now when I send a response back, how should I process it in AJAX success function?
pdf.closed
return render(request, 'generate_report/reports.html', ctx)
Don't try and send it in the Ajax response. Instead, get your view to generate a unique URL for the PDF, then get the JS to redirect the browser to that URL:
view:
return HttpResponse(json.dumps({'url': my_url})
JS:
$.ajax({
type : "POST",
dataType: "json",
url: "/reports/",
data : { 'start_date' : $("#startDate").val() , 'end_date' : $("#endDate").val() },
success : function(result){
var url = result['url'];
window.location = url;
},
The simplest solution would be to call window.open(pdf_url) in "success" callback, where pdf_url is the link to your generated pdf report (which you'll need to pass to response).
This problem has been discussed in the following Question... You might need to go for the jquery plugin for file download and please do not forget to set cookie in the response.
PDF file download through XHR Request
You might need to add a javascript file for the file download and also use the folowing code to generate the request to the server.
$.fileDownload(urlll,{
successCallback: function (url)
{
//success code here
},
failCallback: function (html, url)
{
//error code here
}
});
And on the server side while adding the header etc in the response do the following in response object. i.e.
aResponse.addCookie(cookie);
I hope you can solve the issue and can help others as well.. "Dangling Pointer"

how to read a file using ajax and django?

My Ajax code:
var upfile = $("#file-id").val().split(/[\/\\]/).pop();
$.ajax({
type: 'POST',
url: '/upload/',
data:{"upfile":upfile},
success: function(data) {
if (data['success'] === "true") {
}
},
dataType: 'json'
});
return false;
Django code:
In simple form submit action request.FILES.get('upfile') works. I can read the content of file using read() But in ajax, it is not working. even request.POST.get('upfile') gives me the filename string.
How to solve this issue?
It's normal, by default a form submitted with Ajax will not upload files. You need o have a look to some file upload jquery plugins (there's a few of them, I can not suggest one as I did not try any of these yet)

Categories

Resources