How can I catch server json response while uploading image using Ajax? - python

I have a form which is loaded via jQuery from the external template file:
$('#imguploadform').html(' ').load('{% url upload_form %}');
In template it looks like this:
<img src="{{ MEDIA_URL }}img/misc/upload.png" alt="Illustration" title="myimage" />
<form id="uploadForm" enctype="multipart/form-data" method="post" action="upload_picture/">
{{ form.as_ul }}
<input type="submit" value="Upload" id="uploadImage" />
</form>
I'm trying to upload an image with ajax using jquery form plugin:
var submit_options = {
target: '#picworks',
dataType: 'json',
success: function() {
alert('It Works!');
}
};
$('#uploadForm').submit(function(){
$(this).ajaxSubmit(submit_options);
return false;
});
But then I want to return a json object from server and dynamically load into page an image using it's returned address. I've tried like this:
def upload_picture(request):
dest = save_original(request.FILES['image'])
form = UploadImageForm(request.POST, request.FILES)
res = json.dumps({
"path": dest,
})
return HttpResponse(res, mimetype='application/json')
The problem is that I can't catch a json response in javascript, so my browser shows me just an empty page with json dictionary content. What I'm doing wrong?

Have your success callback take a parameter. That will be the response.

var submit_options = {
target: '#picworks',
dataType: 'json',
success: function(response) {
alert('It Works!');
window.location.href = response.path;
}
};

I solved the problem! The thing is that function which replace form submitting action with an ajax request is called earlier than the form loads from external file. So it should be like this:
$('#imguploadform').html(' ').load('{% url upload_form %}',
function(){
var submit_options = {
dataType: 'json',
success: update_dom
};
function update_dom(data) {
$('#picworks').html('<img src="' + data.path + '" alt="Illustration" />');
}
$('#uploadForm').submit(function(){
$(this).ajaxSubmit(submit_options);
return false;
});
});

Related

can not send file with Axios to django, It's always empty

I'm using axios and django 3.1.6, the problem is that all axios can not send files via post request and in my views request.FILES is always empty. (while sending it as default html form post, it's not empty)
I'm doing it like this
my script.js file
...
$("#myform").submit(function(event) {
event.preventDefault();
});
$("button[type='submit']").click(function() {
let form = $("#myform").serialize()
axios.post(".", form).then((response) => {
if (response.data.status == "success") {
myform.reset();
// other codes here
}
}).catch((error) => {
console.error(error);
})
});
template.html
...
<form method="post", action="." enctype="multipart/form-data" id="myform">
{% csrf_token %}
<!-- inputs .. file inputs -->
</form>
view.py
if request.POST.get("add-medical-record"):
print(request.POST) # i have my data here
print(request.FILES) # it's always empty
...
thanks you guys.
I got it the problem was in script.js file. just send it as new FormData(myform) and that's all. it works.
finally my script.js file
...
$("#myform").submit(function(event) {
event.preventDefault();
});
$("button[type='submit']").click(function() {
let form = new FormData($("#myform")[0])
axios.post(".", form).then((response) => {
if (response.data.status == "success") {
myform.reset();
// other codes here
}
}).catch((error) => {
console.error(error);
})
});

Passing data with ajax to django with post method

I'm try to send data to a django view through ajax with POST method as I saw in one tutorial.
The code I've made is the following (myURL is the URL where I call testview):
$(document).on('submit','#form',function(e){
e.preventDefault();
$.ajax({
type:'POST',
url:'/myURL/',
data:{
HELLO: "I'm inside ajax data"
},
contentType: "application/json",
datatype: 'json',
sucess:function(){
alert("Ajax pass data correctly");
}
})
});
</script>
And in django I'd call HELLO as following. test.html is where I have the html form
if request.method == 'POST':
takeHELLOfromajaxpost = request.POST['HELLO']
return render(request,'test.html',{'dataTakenfromAjax':takeHELLOfromajaxpost})
return render(request,'test.html',{})
Then I would template tagging in the same HTML {{ dataTakenfromAjax }} to verify if I'm taking that data , but nothing happens! I even get no error.
First of all, you are not sending csrfmiddlewaretoken with your request.
Second, you have typo in success argument.
Third, you probably expecting it to completely change html? Than you should add $("body").html() at successful response. That way your variable appear on page.
test.html:
{{ dataTakenfromAjax }}
<form action="" id="form">
{% csrf_token %}
<button type="submit">Submit</button>
</form>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script>
$(document).on('submit', '#form', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '/myURL/',
data: {
csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
HELLO: "I'm inside ajax data"
},
success: function (data) {
$("body").html(data);
}
})
});
</script>

Django csrf token for Ajax

I have given {% csrf_token %} inside the form.
Do I have to give another {% csrf_token %} inside the AJAX $.ajax({ .......... )} ?
<form method="post" data-validate-username-url="{% url 'validate_username' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign up</button>
</form>
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script>
$("#id_username").change(function () {
console.log($(this).val());
var form = $(this).closest("form");
$.ajax({
url: form.attr("data-validate-username-url"),
data: form.serialize(),
dataType: 'json',
success: function (data) {
if (data.is_taken) {
alert(data.error_message);
}
}
});
});
</script>
See below for how I changed your code. The csrf_token is assigned to a variable with Django templating. You can produce this variable in any of your Javascript code.
The token is then included in the header
<script>
var token = '{{csrf_token}}';
$("#id_username").change(function () {
console.log($(this).val());
var form = $(this).closest("form");
$.ajax({
headers: { "X-CSRFToken": token },
url: form.attr("data-validate-username-url"),
data: form.serialize(),
dataType: 'json',
success: function (data) {
if (data.is_taken) {
alert(data.error_message);
}
}
});
});
</script>
The documentation very well explained how to use AJAX
https://docs.djangoproject.com/en/2.1/ref/csrf/
Get this library https://github.com/js-cookie/js-cookie/
Add this var csrftoken = Cookies.get('csrftoken');
The last step is configure ajax setup
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Update to the steps above - as the Django documentation indicates you can use the Javascript Cookie library to do a Cookies.get('csrftoken'). Also, I had to add {% csrf_token %} before the function call. Might be obvious, but I didn't know so providing it here to help others

Pass url with id to html page that is called by another url

I have a template which is called by the url /add which contains multiple registration page that is developed entirely on reactjs. In add.html page that is called by the url /add there is an image upload form too(it is also developed using reactjs) and has ajax code which requires url for posting and i need the different url {% url 'uploadImage' pk %} to provide so that i can saved to its associated instance. In short, the form is in add.html and the form requires id to save data to its associated instance.
Here's my code
urls.py
url(r'^add/$', AddView.as_view(), name="add"), // presents add.html page which displays just multiple form
url(r'^upload/image/(?P<pk>\d+)/$', UploadImage.as_view(), name="uploadImage"), // used for uploading image that is on the add.html page
views.py
class AddView(TemplateView):
template_name = 'rentals/add.html'
class UploadImage(View):
model = Rental
template_name = 'rentals/add.html'
def get(self, request, *args, **kwargs):
return render(request, self.template_name)
def post(self,request,*args,**kwargs):
print(request)
if request.FILES:
rental = Rental.objects.get(pk=request.POST['rental'])
print ('rental is', rental)
for file in request.FILES.getlist('image'):
print('file',file)
image = Gallery.objects.create(image=file, rental=rental)
print('image',image)
return HttpResponseRedirect('/')
add.html
<div id="listing"> // this contains multiple form developed using reactjs code
</div>
{% include 'includes/script.html'%}
<script type="text/javascript">
var data = {
urltag: {% url 'uploadImage' %} // how can i pass url here if i pass with pk i get an error as this templated is called using /add but the form is also in this template which anyhow requires id
}
console.log('url is', data);
$(function() {
app.showListingSpaceForm("listing",data);
});
</script>
ajax code
$.ajax({
url:"/add/space/",
data:sendData,
type:'POST',
success: function(data, textStatus, xhr ) {
$.ajax({
url:"/upload/image/",
data:image,
contentType:false,
processData:false,
type:'POST',
mimeType: "multipart/form-data",
success: function(data) {
console.log('success');
}
});
window.location.href = "http://localhost:8000/";
}
});
return a "pk-user" in Response Header in your view doing
response['pk-user'] = rental.pk
return response
Now you can use the returned user id
$.ajax({
url:"/add/space/",
data:sendData,
type:'POST',
success: function(data, textStatus, xhr ) {
var pk = xhr.getResponseHeader('pk-user');
console.log('pk is',pk);
$.ajax({
url:"/upload/image/"+pk+"/",
data:image,
contentType:false,
processData:false,
type:'POST',
mimeType: "multipart/form-data",
success: function(data) {
console.log('success');
}
});
window.location.href = "http://localhost:8000/";
}
});
should just be
{% url 'uploadImage' 'pk_id' %}
or if you have an object named image do
{% url 'uploadImage' image.pk %}

Ajax is giving back all the html instead of the variable in Django?

I have a Ajax and template like this:
<html>
<body>
<script language="javascript" type="text/javascript">
<!--
//Browser Support Code
function ajaxFunction(){
var ajaxRequest; // The variable that makes Ajax possible!
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
// Create a function that will receive data sent from the server
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
document.myForm.time.value = ajaxRequest.responseText;
}
}
url = '/home'
ajaxRequest.open("GET", url, false);
ajaxRequest.send(null);
}
//-->
</script>
<form name='myForm'>
{% csrf_token %}
Name: <input type='text' onChange="ajaxFunction();" name='username' /> <br />
Time: <input type='text' name='time' id='time' value="" />
</form>
</body>
</html>
And I have simple views like this:
from django.shortcuts import render_to_response, HttpResponse
import simplejson
from django.template.context import RequestContext
import datetime
def home(request):
if request.GET:
a = datetime
return HttpResponse(simplejson.dumps(a), mimetype='application/json')
#return render_to_response('home.html', {'a':a}, context_instance=RequestContext(request))
else:
return render_to_response('home.html', context_instance=RequestContext(request))
Ajax is loading when I press enter but instead of the particular variable all the template is loading in the input box. What's wrong?
This line:
if request.GET:
checks to see if there are any GET parameters. There aren't, because you're not sending any. The URL is just /home. You could use if request.method == 'GET', but I think you're checking for the wrong thing here: a normal request (not Ajax) will also be GET.
What you should do is send the HTTP_X_REQUESTED_WITH header as "XmlHttpRequest", then check request.is_ajax() in the view. Or, as recommended, use a library like jQuery - which sets that for you automatically.
The proper way to detect request type is if request.method == 'GET', instead of if request.GET.

Categories