404 (Not Found) in ajax post url due to file upload - python

jQuery("#myform").submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
jQuery.ajax({
type:'POST',
url:'{% url 'editJobDesc' %}',
data: formData,
cache:false,
contentType: false,
processData: false,
success: function (data) {
alert("Done");
}
});
});
The code works perfectly fine in localhost but shows 404 url not found when hosted on server.
In django views.py:
profile = request.POST.get('profile')
jd = request.FILES.get('jd')
Django urls.py:
path('editJobDesc', views.editJobDesc, name="editJobDesc"),
I found out that error is due to the file I am trying to upload using ajax. If I try to upload other inputs it works fine.
I even tried appending file with formData but still I get the same error.

Related

Make AJAX continue working and update its status on UI even if user redirects or navigates to another page

I'm using Flask and JQuery to try to achieve this but pls feel free to suggest any other stack(React/Angular) if that's super easy.
I have the below AJAX in a poll.js file
$(document).ready(function(){
$('#poll').click(function(){
$('#poll').text("Working...")
$.ajax({
url: '/poll',
data: $('form').serialize(),
type: 'GET',
success: function(response){
console.log(response);
$('#poll').text("Poll")
},
error: function(error){
console.log(error);
$('#poll').text("Poll")
}
});
});
});
and my poll function in app.py is as below:
#app.route('/poll', methods=['GET'])
def poll():
call an api and return the json response
now on the UI if i click the poll button its text changes to working and it calls the function which eventually hits the API.
While this is happening, if click the home menu or navigate elsewhere on the page, i loose the AJAX call.
How do i make the ajax call continue working i.e. calling the api and updating the UI even if we try to redirect to another page or click anywhere else?
I suggest to load the data on initial page load and then refresh after set interval. to achieve this following should give you a kick start
<script type="application/javascript">
jQuery(document).ready(function($){
/* change this
$('#poll').click(function(){
$('#poll').text("Working...")
$.ajax({
url: '/poll',
data: $('form').serialize(),
type: 'GET',
success: function(response){
console.log(response);
$('#poll').text("Poll")
},
error: function(error){
console.log(error);
$('#poll').text("Poll")
}
});
});
*/
//to this it will start with page load and refresh $('#poll') every 5 seconds
var setInt = setInterval($(function(){
$('#poll').text("Working...")
$.ajax({
url:'path to script',
data: $('#form').serialize(), //your html must have form with id="form" for this
type: 'GET',
success: function(response){
console.log(response);
$('#poll').text("Poll")
},
}).fail(function(xhr,ajaxOptin,thrownError){
//console.error(xhr.responseText);
console.error(thrownError);
});
}), 5000);
});
</script>

send metatags through Google Cloud Signed URL with Django

I'm using signed url to get or post/put video fileq on my google storage. My modules refers on signed_url V4 and it's working quite well.
I wanted to add some metadata tags to my requests in order to manage more efficiently the charges related to GCS. But since I added those headers, the requests failed returning a cors policy error : (I have shortened the signature in the block above to make it more readable)
Access to XMLHttpRequest at 'https://test-dev-slotll.storage.googleapis.com/uploads/dave/FR/eaa678c9/2020/9/785f/f45d3d82-785f_full.mp4?X-
Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=dev-storage%40brilliant-tower-264412.iam.gserviceaccount.com%2F20200926%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20200926T093102Z&X-Goog-Expires=3600&X-Goog-SignedHeaders=host%3Bx-goog-meta-account&x-goog-signature=6fbb27e[...]bd0891d21' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
and the detailed message:
<Error>
<Code>MalformedSecurityHeader</Code>
<Message>Your request has a malformed header.</Message>
<ParameterName>x-goog-meta-account</ParameterName>
<Details>Header was included in signedheaders, but not in the request.</Details>
</Error>
The cors are conigured to allow almost everything on my bucket :
[{"maxAgeSeconds": 3600, "method": ["*"], "origin": ["*"], "responseHeader": ["*"]}]
and here is the Python/Django function
def _get_signed_url(self, http_method="GET"):
"""' create a signed url with google storage
create a 'GET' request by default,
add method='w' or 'put' to create a 'PUT' request
get_signed_url('w')->PUT / get_signed_url()->GET
"""
if http_method.lower() in ["w", "put", "post"]:
http_method = "PUT"
else:
http_method = "GET"
signed_url = generate_signed_url(
settings.GS_BUCKET_NAME,
self.file.name,
subresource=None,
expiration=3600,
http_method=http_method,
query_parameters=None,
headers={'x-goog-meta-language':'french','x-goog-meta-account':'david',},
)
return signed_url
As I wrote it above, method get_signed_url() is copied from signed_url V4
if i replace headers = {'x-goog-meta-language':'french','x-goog-meta-account':'david',},
by hearders = {} or headers = None (as it was previously, it works fine
last, when I click on the link given by the signed-url, I got an error message:
The signed url as well as blob uploading or downloading are working fine without the headers for months but I do not see why the server is responding that the header meta tags are malformed...
I will appreciate any help
thanks !
I was getting the same error message when I was performing a GET request on the pre-signed urls from GCP. Adding the content-type: "application/octet-stream" solved it for me.
ajaxCall_getFile = $.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
return xhr;
},
type: 'GET',
url: <PRE-SIGNED URL>,
contentType: "application/octet-stream",
processData: false,
success: function(file_data){
alert("file downloaded");
},
error: function(err) {
alert('Download failed, please try again.');
}
});
As #Sideshowbarker suggests it in his comments, the problem came from the client.
The signed url was used to send files to storage through ajax but no custom header were added to the ajax.
By specifying the headers in the ajax, the PUT request of a signed url with custom metadata works well.
function ajaxSendToStorage(uuid, url) {
// Sending ONE file to storage
var file = getFileById(uuid);
$.ajax({
method: "PUT",
contentType: file.type,
processData: false,
dataType: "xml",
crossDomain: true,
data: file,
url: url,
headers: {"x-goog-meta-account":"david","x-goog-meta-language": "fr"},
success: function() {},
complete: function() {},
});
}

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 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