When using POST request with AJAX in Django 4.0.1 I can't reach the file from the backend using request.FILES. The form used is pretty simple so I can't spot any typos etc.
HTML:
<form id="snipForm" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" id="multiFiles" name="files[]" multiple="multiple"/>
<button id="upload">Upload</button>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
JavaScript: (sorry for quite a long code sample but I can't shrink it more)
$(document).ready(function (e) {
$('#upload').on('click', function (event) {
//Prevent page from reloading
event.preventDefault()
var form_data = new FormData();
// check if there is any file selected
var ins = document.getElementById('multiFiles').files.length;
if(ins == 0) {
$('#msg').html('<span style="color:red">Select at least one file</span>');
return;
}
// add all files
for (var x = 0; x < ins; x++) {
form_data.append("files[]", document.getElementById('multiFiles').files[x]);
}
// obtain CSFR token
csrf_token = $('input[name="csrfmiddlewaretoken"]').val();
// set the headers
headers = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest', 'X-CSRFToken': csrf_token};
$.ajax({
type: 'POST',
url: '/docs/', // point to server-side URL
dataType: "json",
ContentType: "application/x-www-form-urlencoded",
cache: false,
processData: false,
headers: headers,
data: form_data,
success: function (response) { // display success response
console.log("successssssssssssss")
},
error: function (response) {
console.log("NOPEEEEEE")
}
});
});
});
views.py:
from django.views.decorators.csrf import ensure_csrf_cookie
#ensure_csrf_cookie
def generate(request):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
if request.method == 'POST' and is_ajax:
files = request.FILES.getlist('files[]')
if files:
print("file here")
#do some stuff
else:
print("NO FILE AT ALL")
return JsonResponse({...})
Request itself seems to be working console.log('sucessss') is visible after request is completed. Django however has no access to the file. The data with stored file is saved in the form_data but as far as I know we can reach files through mentioned request.FILES['name_of_the_input'].
What might be the cause?
When doing a file upload(with FormData) with $.ajax, you must set contentType and processData to false.
Otherwise jQuery will try to convert you FormData object to a string and set the content type of the request to "application/x-www-form-urlencoded" which is wrong.
The correct content type is multipart/formdata and will be set automatically.
$.ajax({
type: 'POST',
url: '/docs/', // point to server-side URL
dataType: "json",
cache: false,
contentType: false,
processData: false,
headers: headers,
data: form_data,
success: function (response) { // display success response
console.log("successssssssssssss")
},
error: function (response) {
console.log("NOPEEEEEE")
}
});
Related
$("#feedlikes").on("click", function(e){
e.preventDefault();
$.ajax({
type: 'get',
url:'{% url "feedlikes" %}',
data:{},
success: function({
alert("Updated Successfully")
}),
}),
}),
those are my Ajax code help me to get them work.
this is my view:
def feedlikes(request, feed_id):
feed_update= Feeds.objects.get(pk=feed_id)
feed_update.likes = feed_update.likes +1
feed_update.save()
your feedlikes function expect feed_id but you are not supplying in the ajax url. Your ajax url should be
url:'{% url "feedlikes" feed_id=1 %}'
The problem: how to get that feed id in ajax?
You can make a hidden html tag with id equal to #feedlikes-id (eg feedlikes-1) inside #feedlike div or something like that and access just above submitting ajax and store in some variable and set to url then submit.
If you need to update the data you need to pass post method in ajax with csrf_token in headers.
$("#feedlikes").on("click", function(e){
e.preventDefault();
$.ajax({
type: 'post',
url:'{% url "feedlikes" %}',
data:{},
headers: {
'X-CSRF-Token': {{csrf_token}}
},
success: function({
alert("Updated Successfully")
}),
}),
}),
I am trying to delete some elements in database when user clicks on delete icon but as i am sending id through POST request , i am getting empty dictionary ,
{% for skills in seeker_skills %}
<div class="col-md-4">
<button class="btn btn-info mx-2">{{skills.skill_name}}<span class="badge badge-dark ">{{skills.skill_level}}</span></button><span><i class="fas fa-trash-alt delete_skill" data-attr={{skills.id}} style="cursor: pointer;"></i></span>
</div>
{% endfor %}
updated snippet , i am calling it on click
Ajax code
let delete_class_list = $('.delete_skill')
delete_class_list.click(function(e){
let value = this.getAttribute("data-attr")
let contain_icon = this
let contain_label = contain_icon.parentElement.previousSibling
console.log(contain_label)
$.ajax({
url:'/delete_skill/',
method : 'POST',
data: {
skill_id:value
},
dataType: "json",
contentType: "application/json",
success :function(data){
console.log(data)
contain_label.remove()
contain_icon.remove()
}
,
error:function(e){
console.log(e)
}
})
})
My view
#csrf_exempt
def delete_skill(request):
if request.method == 'POST':
data = {}
print('method is post')
job_id = request.POST.get('skill_id')
print(job_id)
try:
Job_Skillset.objects.get(id=job_id).delete()
data['status'] = 'deleted'
except ObjectDoesNotExist:
data['status'] = 'nodata'
return JsonResponse(data,safe=False)
You're setting your content type to application/json which is incorrect, remove it.
$.ajax({
url:'/delete_skill/',
method : 'POST',
data: {
skill_id:value
},
dataType: "json",
success :function(data){
console.log(data)
contain_label.remove()
contain_icon.remove()
}
,
error:function(e){
console.log(e)
}
})
I am struggling to figure out why my code is returning an error that is being caused by using CSRF in an Ajax call. The error is this:
Uncaught TypeError: Cannot read property 'value' of null
at HTMLUListElement.<anonymous>
Here is my AJAX Call including setup:
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$.ajax({
type: "POST",
url : '/api/uservenue/',
data: {
'cafeName': cafeName,
'list_id': 1,
csrfmiddlewaretoken: document.querySelector('input[name="csrfmiddlewaretoken"]').value
},
success: function(data){
console.log('User clicked: ' + data)
},
failure: function(errMsg) {
alert(errMsg);
}
});
Here is my views.py file
[...]
class UserVenue(viewsets.ModelViewSet):
serializer_class = UserVenueSerializer
queryset = UserVenue.objects.all()
#ensure_csrf_cookie
def get_queryset(self):
cafeName = self.request.GET.get('cafeName', None)
print(cafeName)
return UserVenue.objects.all()
[...]
What I've tried
My JS script is at bottom of html file.
I've tried a bunch of different edits and tweaks based on reading through documentation/SO/Reddit suggestions.
I tried using method_decorators, but this seemed to raise more errors.
I'd be grateful for any advice.
Thanks!
I'm using ajax in Django to activate add to favorites button, here are my files
urls
path('<int:pk>/favorite_item/', views.favorite_item, name='favorite_item'),
views.py
#login_required
def favorite_item (request, pk):
favitem = get_object_or_404(Item, pk=pk)
data = {
'is_fav': Favorite.objects.filter(user=request.user, item=favitem).exists(),
}
if data ['is_fav']:
Favorite.objects.get(user=request.user, item=favitem).delete()
else:
new_entry = Favorite.objects.create(item=favitem, user=request.user)
return JsonResponse(data)
finally HTML
only the part of the script
{% block javascript %}
<script>
$("#add_to_fav").click(function () {
console.log( $(this).val() );
});
$.ajax({
url: form.attr("data-favorite_item-url"),
data: form.serialize(),
dataType: 'json',
success: function (data) {
$('.results').html(data);
},
});
</script>
{% endblock %}
Now when I click the element that should trigger the whole action, the function is already working and the item is removed or added to db, but it takes me to another page which only has 1 sentence ({"is_fav": true}) or ({"is_fav": false})
You need to use preventDefault to stop your browser from actually going to the linked page when the link is clicked. You need to change lines 3 and 4 of the code you included like this:
{% block javascript %}
<script>
$("#add_to_fav").click(function (event) {
event.preventDefault();
console.log( $(this).val() );
});
$.ajax({
url: form.attr("data-favorite_item-url"),
data: form.serialize(),
dataType: 'json',
success: function (data) {
$('.results').html(data);
},
});
</script>
{% endblock %}
I am trying to send GET request to Django. In the script:
$http({
method: 'GET',
url: 'response/',
data: 'test=data',
}).success(function(data, status, headers, config){
console.log(data);
});
In the view response() function, if I try
def response(request):
data = json.loads(request.body)
return HttpResponse(data)
I will get 500 (INTERNAL SERVER ERROR). If I try
def response(request):
data = request.body
return HttpResponse(data)
the returned data is empty. I wonder what is happening?
do it like this:
$http({
method: 'GET',
url: 'response/',
data: $.param({
'test': 'data
})
}).success(function(data, status, headers, config){
console.log(data);
});
and use request.GET -
def response(request):
data = request.GET.get('test')
return HttpResponse(data)
We can use the code like this.
$http({
method: 'GET', url: '../../load/',
data: {'test': 'Nath'},
header: {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(function (data) {
var ck = data.data;
}, function(response) { console.log("failed to load data."); });
views will be
def response(request):
data = request.GET.get('test')
return HttpResponse(data)
it worked..