how to upload file on django server using javascript/jQuery and ajax - javascript

After having spent hours, I need help to match the javascript code to the django codes.
I am using the "minimal-django-file-upload-example" version django 1.8 from the git https://github.com/axelpale/minimal-django-file-upload-example.
In standalone, it works very well.
Now i try to upload file from javascript and i do not succeed to make it works.
Javascript Code
function UploadBlob(zip)
{
var ZipFileBlob = zip.generate({type:"blob"});
var fd = new FormData();
fd.append('data', ZipFileBlob);
fd.append('fname', 'ZipOfImage.zip');
fd.append('enctype','multipart/form-
$.ajaxSetup({
type: 'POST',
url: 'http://127.0.0.1:8000/myapp/list/',
enctype: "multipart/form-data",
headers: { "X-CSRFToken": getCookie("csrftoken") }
});
$.ajax({
data: fd,
processData: false,
contentType: false
}).done(function(data) {console.log(data);});
}
Django code
in forms.py
class DocumentForm(forms.
docfile = forms.FileField(label='Select a file')
in views.py
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile = request.FILES['docfile'])
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('myproject.myapp.views.list'))
else:
print "invalid form"
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render_to_response(
'list.html',
{'documents': documents, 'form': form},
context_instance=RequestContext(request)
)
The code run up to the request.method == 'POST'. After, i do not know if i should add field to the ajax requests (and which ones) or if there is a more suitable form in django or do something else.
Please help!

Related

Django & AJAX combined

;0mage to process it on server and get a response without refreshing the page. I look up for some tutorials how to use AJAX and jQuery to do this but I don't have much knowledge at this matter. I'm completly stuck and have no idea what shall I do next. So far my code looks like this:
models.py
class Snip(models.Model):
#some fields
snip = models.FileField(upload_to="snips/")
latex = models.TextField(default = '')
forms.py
from .models import Snip
from django import forms
class SnipForm(forms.ModelForm):
class Meta:
model = Snip
fields = ['snip']
HTML:
<form id="snipForm" method="POST" enctype="multipart/form-data">
<input type="hidden" name="csrfmiddlewaretoken" value="...">
<div class="row align-items-center">
<div class="col-12">
<label for="id_snip">Snip:</label>
<input type="file" name="snip" required="" id="id_snip" class="btn-success p-2 rounded">
<input type="submit" name="upload" id="upload" class="btn btn-secondary">
</div>
</div>
</form>
JavaScript/AJAX
var upload_btn = document.getElementById("upload")
upload_btn.addEventListener('click', function () {
var form_data = new FormData();
var ins = document.getElementById('id_snip').files.length; //
if(ins == 0) return console.log("No snip!!!")
form_data.append("file[]", snip.files[0]);
csrf_token = $('input[name="csrfmiddlewaretoken"]').val();
form_data.append("csrfmiddlewaretoken", csrf_token);
headers = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'};
console.log(form_data);
console.log(headers);
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest');
}
});
$.ajax({
type: 'POST',
url: 'https://localhost:8000/docs/', // point to server-side URL
dataType: "json",
ContentType: "application/json",
cache: false,
processData: false,
headers: headers,
data: form_data,
success: function (response) { // display success response
console.log("SUCCESSSSSSSSS")
},
error: function (response) {
console.log("NOPEEEEEE")
}
});
});
views.py
from django.shortcuts import render
from django.contrib.auth.models import User
from .models import Snip
from .forms import SnipForm
from django.http import JsonResponse
from django.core import serializers
def generate(request):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
if is_ajax and request.method == "POST":
file = request.FILES['snip']
processed_image = "Some text from OCR"
return JsonResponse({'text':'Yay, I got text from OCR'})
if request.method == 'GET':
Users = User.objects.all()
form = SnipForm()
user_list = []
for user in Users:
if user.get_full_name():
user_list.append(user.get_full_name())
return render(request, "new.html", {'Users': user_list, 'form': form})
To sum up:
The image is loaded to id_snip input tag. After clicking on id="upload" button it should be sent to django server and then to outer OCR API to receive some text back. Then it's supposed to be displayed on the front end without refreshing the page. However after clicking submit I get error:
The view docs.views.generate didn't return an HttpResponse object. It returned None instead.
My first thought was to check the is_ajax value. It occured to be false. So my question is:
How can I check if the request "is AJAX"? I know in previous versions of django it was is_ajax() method but since some like 3.1 version is not recommended
Is there any simple way to do it? My goal is to put received response (text) somewhere else on the page.
#UPDATE:
So I changed a bit of JavaScript/AJAX code above due to this post
I added
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest');
}
});
However on Django error page I can't see any META info such as HTTP_X_REQUESTED_WITH.
What more it seems that no data is appended to the form_data:
Output of:
console.log(form_data)
console.log(headers)
is:
FormData {}
{HTTP_X_REQUESTED_WITH: 'XMLHttpRequest'}
For now I get exactly the same error message, which is The view docs.views.generate didn't return an HttpResponse object. It returned None instead.
What might be wrong with this code? It seems fine for me

How to handle request json data in flask

I would like to send json formatted data from my html page to a url on the click of a button, but currently the data is not getting updated to the url. I've included here a small subset of the data i'm trying to post. The GET method works fine for posting initial output to the url. The result of the ajax request is the alerted error output. How can I use POST to successfully update the output to the url?
The html:
<button type="submit" class="btn-sm btn-success btn-space" id ="commitButton" name="commitButton" value="enter">Commit</button>
Javascript:
<script>
document.getElementById('commitButton').onclick = function() {
$.ajax({
url: "/processjson",
type:'POST',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
"dataType": "json",
"data": {"schema": {"fields":[{"name":"index","type":"integer"},{"name":"OB_TIME","type":"datetime"},{"name":"LATITUDE","type":"number"},{"name":"LONGITUDE","type":"number"}]}, "data": [{"index":0,"OB_TIME":"2015-09-03T00:00:00.000Z","LATITUDE":21.9,"LONGITUDE":-152.0}]},
"contentType": "application/json",
success: function(result) {
alert('ok');
},
error: function(result) {
alert('error');
}
})
};
</script>
Flask:
#app.route('/processjson', methods=['GET','POST'])
#login_required
def processjson():
if request.method == 'GET':
return jsonify({'result':'Test'})
# getting the table data when the commit button is pressed
if request.method == 'POST':
# gets jsonified data and convert it to a python data structure (dictionaries)
data = request.get_json()
fields = data['schema']['fields']
tableData = data['schema']['data']
return jsonify({'result':'Success!','tableData' : tableData})
Place the json data inside the request body.
You can access the request body with request.form.get('data') to get a json string. This can be load to a dict using json.load(json_str).
request.get_json() parse form data as json, but this would work if you are submitting as form data. Looking at the JS snippet, it looks like you are not submitting it as form data (you are making an ajax call), so your data will be available in the property request.json
you can use like this : request.json

Django: Ajax not receiving data from server response

I am pretty new to Django and I am trying to figure out how to add content dynamically coming from a python script without reloading a page.
Currently, I have two functions in my views.py file. One handles uploading a file (home), and the other handles calling a python script and handling the file (handle). The reason I separated it like this is because I want to sequentially populate a HTML table as the python script works with the uploaded file.
However, my ajax function is not receiving any data from the handle function's http response and I am not sure why. Neither the success nor the error functions are being called. This is really strange because the print statement in the handle function in views.py prints successfully with data.
Views.py
i=0
uploaded_file = None
def home(request):
if (request.method == 'POST'):
file_form = UploadFileForm(request.POST, request.FILES)
if file_form.is_valid():
global uploaded_file
uploaded_file = request.FILES['file']
print(uploaded_file)
else:
file_form = UploadFileForm()
return render(request, 'personal/home.html', {'form': file_form})
def handle(request):
# TODO make ajax wait for a response from 'home'
# so I don't have to wait for 1 second
time.sleep(1)
data = {}
data['Name'] = fileName(uploaded_file)
if(request.is_ajax()):
print(data) # prints succesfully
return HttpResponse(json.dumps(data),
content_type="application/json")
home.html
<script type = "text/javascript" language = "javascript">
function post_tables(data) {
alert(data)
}
$(document).ready(function(post_tables) {
$("#upload").click(function(event){
$.ajax( {
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "get",
url:'/handler',
success: function(data) {
console.log("over here")
post_tables(data)
},
error: function(data) {
console.log("down here")
post_tables("error being thrown")
}
});
});
});
</script>
urls.py
urlpatterns = [
path(r'', views.home, name='home'),
path(r'handler', views.handle, name='handle'),
]
I explained the whole process ajax django to you. Perhaps your problem will be solved. good luck.
views.py
def handle(request):
if request.method == 'POST':
data = request.POST
field_example = data.get('field_example')
return JsonResponse(data)
else:
data = request.GET
field_example = data.get('field_example')
return JsonResponse(data)
home.html
<form id="upload">
{% csrf_token %}
<input type="text" name=field_example>
.
.
.
</form>
urls.py
urlpatterns = [
path(r'', views.home, name='home'),
path(r'handler/', views.handle, name='handle'),
]
js code in home.html:
$("#upload").submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: "{% url 'handle' %}",
type: 'GET',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (data) {
console.log("over here")
post_tables(data)
},
error: function (data) {
console.log("down here")
post_tables("error being thrown")
}
});
});

Why an ajax call doesn't give .is_ajax()=True?

My template.html:
...
<button class="btn btn-success" onclick="save_post(event, 'publish')">Publish</button>
...
My javascript.js:
function save_post(event, action) {
event.preventDefault();#new line
var tag_string=document.getElementById('id_tags').value;
if (action=='publish' || action=='draft') {
var url_post='/blog/post/new/'
} else {
var url_post='/blog/post_edit/'
};
$.ajax({type: 'POST',
url: url_post,
data: {
tagstring: tag_string,
action: action
},
success: function (lista) {
//code
}
});
};
My views.py:
#staff_member_required
def post_new(request):
context_dict=[]
if request.method == "POST":
if request.is_ajax():
#code
...
else:
form = PostForm()
return render(request, 'blog/post_edit.html', context_dict)
My url.py:
app_name = 'blog'
urlpatterns = [
...
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
...
My views is called by the url (browser), then the button call a javascript function and it call (with ajax) again the same view, this time with request.method = "POST" and this works, but request.is_ajax() gives False.
For call post_edit (probabily) I need the id of the post. Where can I get it?
Should I pass it to save_post() from the template?
Edit: ignore these lines below
Also should I use preventDefault() somewhere?
Thank you
Edit: now I use preventDefault() but it gives this error:
Not Found: /blog/post_new/
[26/Jan/2018 19:07:20] "POST /blog/post_new/ HTTP/1.1" 404 10871
and ajax dosn't call the view. Edit: I solved this problem, but I continue tomorrow :)
Your Ajax code some problems and view is correct
I have attached my Code attached Image and code
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : 'myajaxview', // the url where we want to POST
data :{
'csrfmiddlewaretoken': '{{csrf_token}}',
'text': text,
'search': search,
'email': email,
'url': url,
'telephone': telephone,
'password': password,
'number': number,
},
dataType : 'json', // what type of data do we expect back from the server
encode : true
})

Django : send form in ajax with files

I know, i know, there are already some questions on this subject and believe my i've tried many many thing but still, i can't make it work.
I had a page with the form, tu upload an img with a comment (so a textarea and a file input). The thing is, i don't want to have a specific page for this form, so i have a popin with the form in a page. So i decided to do it in ajax (so the user can stay on the page and upload severals photos).
But I keep having a mistake, 'the comment field is required'. It looks like the form sent is empty. Following documentation and many (MANY) advices this is how i did it :
Form.py
class UploadPhotoForm(ModelForm):
class Meta:
model = Photo
fields = ['picture', 'comment']
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super(UploadPhotoForm, self).__init__(*args, **kwargs)
def save(self):
photo = super(UploadPhotoForm, self).save(commit=False)
artist = Artists.objects.get(user=self.request.user)
photo.artist = artist
photo.save()
return photo
views.py (the one handling the form : i changed it when i wanted to make ajax):
#login_required
#require_POST
def upload_photo_artist(request):
form = UploadPhotoForm(request.POST, request.FILES, request=request)
if form.is_valid():
form.clean()
form.save()
response = {
'code': 1,
'message': 'success',
}
return HttpResponse(
json.dumps(response),
content_type='application/json'
)
else:
response = form.errors.as_json()
return HttpResponse(
json.dumps(response),
content_type='application/json'
)
And the JS part :
$('#upload_photo').submit(function(e){
e.preventDefault();
var csrftoken = getCookie('csrftoken');
var data = new FormData($(this)[0]);
data.append('csrfmiddlewaretoken', csrftoken);
//data.append('comment', $(this).find('div.input-field').find('textarea').val());
//data.append('photo', $(this).find('div.file-field').find('input:file')[0]);
$.ajax({
url: "/photo/upload",
type: "POST",
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
data: data,
processData: false,
contentTYpe: false,
success: function(data) {
if(data['code']== 1) {
location.reload();
}
else {
alert(data);
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
});
So it looks like the formData object send is just an empty thing, but i've read the documentation and some examples and i don't see what am I doing wrong here.
You can see in comment the append() method of FormData object. I've tried to just declare a new FormData object empty and add then the fields.
In last try, i had directly the CSRFToken in the FormData object, but still, doesn't work.
If someone can help, that'd be great !

Categories