Django-ajax: CSRF verification failed. Request aborted - ajax

I am working with django server side form to save details in DB.
<form id="form_save_file" enctype="multipart/form-data">
{% csrf_token %}
<label class="control-label col-md-4">File:</label>
<div class="col-md-8">
{{form.fa_file}}
</div>
<label class="control-label col-md-4">Name:</label>
<div class="col-md-8">
{{form.name}}
</div>
</form>
I am using ajax to post request.
$("#form_save_file").submit(function(e) {
$.ajax({
type: "POST",
url: '/url/',
data: $("#form_save_file").serialize(),
contentType: false,
processData: false,
success: function(data){}
});
I have included middleware classes in settings.py
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'request.middleware.RequestMiddleware'
)
When I removed contentType and processData in ajax request, request.FILES is empty in views.py and otherthings are working fine.

contentType option to false is used for multipart/form-data forms that
pass files.
When one sets the contentType option to false, it forces jQuery not to
add a Content-Type header, otherwise, the boundary string will be
missing from it. Also, when submitting files via multi-part/form one
must leave the processData flag set to false, otherwise, jQuery will
try to convert your FormData into a string, which will fail.
To try and fix your issue:
You are using jQuery's .serialize() method which creates a text string
in standard URL-encoded notation.
You need to pass un-encoded data when using "contentType: false".
Try using "new FormData" instead of .serialize():
Source: https://stackoverflow.com/a/20863123/3345051
Revised Code:
$("#form_save_file").submit(function(e) {
e.preventDefault();
var $this = $(this);
var postURL = '/url/';
var formData = new FormData(this);
$.ajax({
type: "POST",
url: postURL,
data: formData,
mimeType: "multipart/form-data",
contentType: false,
cache: false,
processData: false
})
.done(function(response) {
// Do something if POST is successful
})
.fail(function() {
// Do something if POST is unsuccessful
})
})

disabled csrf on particular view with #csrf_exempt decorator and build custom security with a random number/string

Related

Laravel - AJAX file upload returning null

This is my ajax request:
var files = $('#imgur_attach')[0].files;
if(files.length > 0){
var fd = new FormData();
// Append data
fd.append('file',files[0]);
fd.append('_token',$globalToken);
$.ajax({
type: "POST",
dataType: "json",
contentType: false,
processData: false,
url: host + "/attach-comment-image/" ,
data: {fd},
Controller:
public function attach(Request $request) {
$this->validate($request, [
'file' => 'image|required',
]);
When sending this ajax request, the validator tells me that the "file" field is required. Trying to return request->get('file') returns null.
However, when I do console.log(fd); before the ajax request, it returns the following:
Why is this happening? I don't normally upload files with AJAX over a regular POST request, so I don't understand what I'm missing.
Try stringify data before sending like this:
$.ajax({
...
data: {fd: JSON.stringify(fd),
...
you need to add multipart form data
contentType: "multipart/form-data",
Wrapping the input around with a form tag like this did the trick:
<form method="POST" enctype="multipart/form-data">
Not sure why setting contentType: "multipart/form-data" in the ajax request doesn't work, but this solution works so I'll just use this instead.

Ajax link does not send POST request

I have the following ajax link:
#Html.AjaxActionLink(item.Name, "https://test.testspace.space/storage/Data/stream?tokenValue=e58367c8-ec11-4c19-995a-f37ad236e0d2&fileId=2693&position=0", new AjaxOptions { HttpMethod = "POST" })
However, although it is set to POST, it seems that it still sends GET request.
UPDATE:
As suggested below, I also tried with js functuion like this:
function DownloadAsset() {
alert("downloading");
$.ajax({
type: "POST",
url: 'https://test.testspace.space/storage/Data/stream?tokenValue=add899c5-7851-4416-9b06-4587528a72db&fileId=2693&position=0',
success: function () {
}
});
}
However, it still seems to be GET request. Parameters must be passed as query and not in the body of the request because they are expected like that by the target action. I don't know why (it would be more natural to have GET request) but back-end developer designed it like this due to some security reason.
If I use razor form like this, then it works:
<html>
<form action="https://test.testspace.space/storage/Data/stream?tokenValue=2ec3d6d8-bb77-4c16-bb81-eab324e0d29a&fileId=2693&position=0" method="POST">
<div>
<button>Send my greetings</button>
</div>
</form>
</html>
However, I can not use this because I already have bigger outer form on the page and I'll end up with nested forms which is not allowed by razor/asp.
The only way is to use javascript but for some reason it does not make POST request.
#Html.AjaxActionLink will generate to <a> tag,and tag will only have HttpGet request method.If you want to send HttpPost with <a> tag,you can use it call a function with ajax,here is a demo:
link
<script>
function myFunction() {
$.ajax({
type: "POST",
url: "https://test.testspace.space/storage/Data/stream",
data: { tokenValue: "e58367c8-ec11-4c19-995a-f37ad236e0d2", fileId: "2693", position:0 },
success: function (data) {
}
});
</script>
Since you want to make a POST request, but the values need to be as query string params in the URL, you need to use jquery.Param.
see https://api.jquery.com/jquery.param/.
You should set the params, like below :
$.ajax({
url: 'your url',
type: 'POST',
data: jQuery.param({ tokenValue: "your token", fileId : "2693", position: 0}) ,
...
Try this instead,
First remove the action url from the from
Second put the result in the success function to return response
and for parameters, I always use FormData() interface to post with Ajax
And last don't forget to include dataType, contentType, processData to not get an unexpected behavior
your code will look like this
var form_data = new FormData();
form_data.append('tokenValue' ,'add899c5-7851-4416-9b06-4587528a72db&fileId=2693');
form_data.append('position' ,'position');
$.ajax({
type: "POST",
dataType: 'json',
contentType:false,
processData:false,
data: form_data,
url: 'https://test.testspace.space/storage/Data/stream',
success: function (result) {
}
});

Keep input type file in a hidden input for AJAX submit

I have an input to upload an excel file and a hidden input
<input type="file" id="file">
<input type="hidden" id="file_submit">
When I choose file in input type file, I want to set its value to hidden input below and retrieve in AJAX function, then I will reset input file for next upload, prevent ERR_UPLOAD_FILE_CHANGED error.
Here is my code in AJAX:
var formData = new FormData();
formData.append('file', $('#file_submit').val());
$.ajax({
url: "{{ route('admin.handle-import') }}",
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
method: "POST",
data: formData,
enctype: 'multipart/form-data',
processData: false,
contentType: false,
success: function(res) {
$('file').val(''); //reset input file
}
});
I tried this code to set value for hidden input:
document.getElementById('file').onchange = function() {
$('#file_submit').val($(this).prop('files'));
};
And in my controller, I get by code $request->file;. But it only return "[object FileList]". I really don't know what I have to do now.
Can you give me a solution for this?
Thank you very much

Converting formData to forms.Form in django

I would like to allow user to key in a quiz code and gets an alert to tell whether if the code is still invalid without refreshing the page. I already read a lot of Django AJAX and JQuery tutorials but most of them seem outdated because they do not cover the part where csrf token must be send.
In my settings.py, I set CSRF_USE_SESSIONS to True.
This is my forms.py
class codeForm(forms.Form):
code = forms.IntegerField(label='Question Code')
In my html file, I have this
<form class="card__form" id="code-form" method="POST">
{% csrf_token %} <script type="text/javascript"> // using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val(); </script> {{form.as_p}
<center><input type="submit" class="btn btn-primary card__submit" id="submit_code"></center>
Just before the tag, I have this :
<script>
$(document).ready(function(){
$("#submit_code").click(function(){
alert("Text: ");
event.preventDefault();
var myform = document.getElementById("code-form");
var form = new FormData(this);
form.append('csrfmiddlewaretoken', csrftoken);
$.ajax({
data : form,
dataType:'json',
type: 'POST',
method: 'POST',
url: '{% url 'student:process_code' %}',
contentType: false,
processData: false,
success: function(context) {
alert(context.msg);
},
error: function(context) {
alert(context.msg);
}
});
});
});
</script>
In my views.py
def process_code(request):
context = {}
if request.method == 'POST':
form = codeForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
code = cd.get('code')
print('yay')
if code.isdigit():
The unexpected result was the form is not valid (form.is_valid() = false). Thus, I think my formData object is not converted to a valid forms.Form type.
I also tried to use form = codeForm(request.POST['code']) but it return more error.
How can I get around this? I prefer not to use serialize() because I read that it cannot be used for uploading files which will be my next feature to work on after this has settled. I wanted to use forms.Form because it has cleaned_data method. If you could provide a good solution although not using forms.Form but with good reasoning, I will appreciate it. Thank you so much
try FormData(myform), not "this"

ajax query based on model form sends no data to server

I have a model based form:
class CommentForm(ModelForm):
class Meta:
model = Comments
fields = ['comments_text']
In html:
<form action="" method="post" id = "comment_form">
{% csrf_token %}
{{form}}
<input type="submit" class="button" value="Добавить комментарий" id = "add_comment">
</form>
When making an ajax query to add comment, it sends no input data from the form to view:
$(document).ready(function()
{
$("#comment_form").submit(function(e){
$.ajax({
url: url_,
type: "post",
success: function(result){
alert(result);
}
});
});
});
What's the reason? Console error: POST http://127.0.0.1:8000/articles/addcomment/1/ net::ERR_CONNECTION_REFUSED
When making an ajax query to add comment, it sends no input data from the form to view:
If you're using ajax, you'll need to pass the parameters manually through data.
$.ajax({
url: url_,
type: "post",
data: $('#comment_form').serialize(),
success: function(result){
alert(result);
}
});
What's the reason? Console error: POST http://127.0.0.1:8000/articles/addcomment/1/ net::ERR_CONNECTION_REFUSED
Try leaving out the url parameter in your ajax request

Resources