I am trying to implement AJAX form submission for my Django forms.
The files are getting submitted without AJAX, so the logic at the serverside seems to be working. and with ajax, the rest of the values except the files get submitted.
Here is the code that I am implementing,
AJAX form Submission
(function() {
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
crossDomain: false, // obviates need for sameOrigin test
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
})();
jquery
$('#save-form').live('submit', function(event) { // catch the form's submit event
event.preventDefault();
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // get the form data
type: $(this).attr('method'), // GET or POST
url: '/save/', // the file to call
success: function(response) { // on success..
$('#modalsave-form').html(response); // update the DIV
}
});
return false;
});
HTML Form
<form class="form-horizontal" id="save-form" enctype="multipart/form-data" method="post" action="/save/">
<div class="control-group">
<label class="control-label" for="id_body">Write Something</label>
<div class="controls">
<textarea class="typeaheadfun" id="id_body" rows="3" cols="100" name="body" placeholder="Scribble Body" style="width: 455px;"></textarea>
</div>
</div>
<div class="control-group">
<label class="control-label" for="id_media">Add a File</label>
<div class="controls">
<input type="file" name="media" id="id_media"/>
</div>
</div>
<hr>
<input class="btn btn-primary pull-right" type="submit" value="Post!" />
<br>
{% csrf_token %}
</form>
When you submit an HTML form it usually sends form's data to the server using either GET or POST data HTML headers. When however you need to send binary data or attached file(s) to the server efficiently, HTML as part of it's spec has a different method for sending such data. enctype attribute of <form> tag specifies using which method should the browser send the data to the server. To send files, multipart/form-data is widely used encoding method.
When you try to send form without ajax, browser sends file data to the server using multipart/form-data encoding however when you submit the form using ajax you do the following:
data: $(this).serialize()
That step does not encode data the same way as server expects the data hence your ajax does not work.
To make it work, instead of manually submitting form's data, you should submit the whole form using ajax. Doing it manually is tricky plus there are plugins which do that already. One such plugin is jQuery Form Plugin. It allows to submit the whole form using ajax. The following is js code which should give you an idea on how to integrate it with your setup:
$('#save-form').live('submit', function(event) {
event.preventDefault();
$(this).ajaxSubmit({
url: '/save/', // the file to call
success: function(response) {
$('#modalsave-form').html(response);
}
});
return false;
});
Another option is to use the FormData interface that absolves the need for a plugin
https://developer.mozilla.org/en-US/docs/Web/API/FormData
Sample Code: (Adapt to suit your needs)
`
$('#fupload').click(function(){
var xhr = new XMLHttpRequest();
var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
$.ajaxSetup({
headers: { "X-CSRFToken": token }
});
var formData = new FormData($('form')[0]);
formData.append('file',xhr.file);
$.ajax({
url: '/myurl/', //server script to process data
type: 'POST',
xhr: function() { // custom xhr
myXhr = xhr;
//if(xhr.upload){ // check if upload property exists
// xhr.upload.addEventListener('progress',progressHandlingFunction, false);
// for handling the progress of the upload
//}
return xhr;
},
// Form data
data: formData,
//Ajax events
success: function(server_response){
$( '#path' ).val("Success");
},
error: function(jqXHR, textStatus, errorThrown ){
$( '#path' ).val(errorThrown);
},
//Options to tell JQuery not to process data or worry about content-type
cache: false,
contentType: false,
processData: false
});
});
`
Related
I am new to Django and Ajax. I have a dropdown that is populated from a database. I want another field to populate based on the selection made in the dropdown. I am getting the return value, but it is not populating the form field. Console.log shows the value being returned. It just never shows on the form field and I am sure the field name is correct. In the browser I get 600. How do I get the 600 into the #id_Deductable field? Any help would be greatly appreciated.
`
<form method="POST" id="BaseQuoteForm" data-agent-url="{% url 'ajax-load-agent' %}">
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-success btn-block" type="submit" value="Add">
</form>
<script
src="https://code.jquery.com/jquery-3.6.1.js"
integrity="sha256-3zlB5s2uwoUzrXK3BT7AX3FyvojsraNFxCc2vC/7pNI="
crossorigin="anonymous"></script>
<script>
$("#id_Agency").change(function () {
var url = $("#BaseQuoteForm").attr("data-agent-url"); // get the url of the `load_cities` view
var Agency = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= localhost:8000/hr/ajax/load-cities/)
data: {
'Agency_id': Agency // add the country id to the GET parameters
},
success: function (data) { // `data` is the return of the `load_cities` view function
console.log(data);
$("#id_Agent").html(data); // replace the contents of the city input with the data that came from the server
}
});
});
</script>
<script>
$("#id_Primary_Plan").change(function () {
var url = $("#BaseQuoteForm").attr("data-agent-url"); // get the url of the `load_cities` view
var PlanData = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= localhost:8000/hr/ajax/load-cities/)
data: {
'PlanData_id': PlanData // add the country id to the GET parameters
},
success: function (data) { // `data` is the return of the `load_cities` view function
console.log(data);
$("#id_Deductable").html(data); // replace the contents of the city input with the data that came from the server
}
});
});
</script>
`
I am adding ajax to my website. I originally had this button:
{% for item in notifications %}
<a class='delete' href="{% url 'delete' item.slug %}">
But changed it to Ajax.
{% for item in notifications %}
<a class='delete'>
$(document).on('click', '.delete', function (e) {
$.ajax({
url: '/users/ajax/delete/',
data: {
// here I was to call the 'delete' function in the 'django.notifications' package
// something like 'notifications.delete(slug)'
},
dataType: 'json',
success: function (data) {
alert("Working");
}
});
});
This Ajax fires correctly, but I don't know how to get item.slug in Ajax. I guess I could do this <a class='delete' slug="{{ item.slug }}"> and access the slug, but it seems really sloppy.
Is there a way to pass an object's attributes to Ajax without setting it as a value within the html code itself?
Thank you.
You can store the value of the notification in a variable while rendering the HTML as shown below in the HTML section. Once you have notifications value in your script code. You can check the index of the clicked anchor and retrieve the item associated with that index.
$(document).on('click', '.delete', function(e) {
let elem = $(this);
$.ajax({
url: '/users/ajax/delete/',
data: {
// here I was to call the 'delete' function in the 'django.notifications' package
// something like 'notifications.delete(slug)'
},
dataType: 'json',
success: function(data) {
alert("Working");
//new code below
let index = $("a.delete").index(elem);
let item = notifications[index];
//You can access slug and other attributes of item now.
}
});
});
<script>
const notifications = {% notifications %}
</script>
How I can call a Django API from another Django Project (or from any other project) and get the response back after some processing on the same calling page (the page from which I called the API)
I am calling the API from form action ....but API shows the response in a new blank page
Here is API CODE: (//skipping some code to avoid confusion)
def IdealWeight(request):
#defining a list of data to send back to html
list_of_data=[]
list_of_data.append(name)
list_of_data.append(fatherName)
list_of_data.append(registration)
print(list_of_data)
# outPut_Data = ast.literal_eval(list_of_data)
# return render(request,'LibraryForm.html',{'data1':outPut_Data})
return JsonResponse(list_of_data,safe=False)
I want list_of_data on the calling page in some variable.
Here is my HTML Code from which i am calling the API:
<form action="http://127.0.0.1:8000/idealweight/?image/" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" class="form-control-file" name="image" onchange="readURL(this);" required>
<input type="submit" class=" btn btn-primary" title="Process" value="Process" id="processButton">
</div>
{{ data1 }}
</form>
From HTML page, I am sending a picture to API (API build in Django)
and from that, I want to send an array or list of data extracted from the image and want to show that on same HTML page....................from which I called the API how I can do that?
hope I am clear what I want?
Using an Ajax call would be better choice. you would be doing something along the line.
$(document).ready(function (e) {
$('#upload').on('click', function () {
var file_data = $('#file').prop('file');
var form_data = new FormData();
form_data.append('file', file_data);
$.ajax({
url: 'http://127.0.0.1:8000/idealweight/?image/',
contentType: false,
data: form_data,
type: 'post',
success: function (response) {
// use response to update html
},
error: function (response) {
// use response to update html
}
});
});
});
and your template would be something like
<input type="file" id="file" name="file"/>
<button id="upload" type="button">Process</button>
note: you might get cross origin request block error. so you have to allow that explicitly.
I am adding a comment functionality in my project. And I am using ajax to make it dynamic so that when the user clicks on the comment submit button it will be added in the comment section dynamically without refreshing the page. But the problem is when prepending a form using ajax I cant add csrf token like this
{% csrf_token %}
in the form because ajax wouldn't understand it and take it as text.
function getids(postid){
console.log(postid)
$(postformid).one('submit', function(event){
event.preventDefault();
console.log(event)
console.log("form submitted!") // sanity check
create_comment(posted);
});
}
// AJAX for posting
function create_comment(postid) {
console.log("create comment is working!") // sanity check
console.log(postid)
console.log(talkid)
$.ajax({
url : "create_comment/"+postid, // the endpoint
type : "POST", // http method
data : { the_comment : $(cmtext).val() }, // data sent with the post request
// handle a successful response
success : function(json) {
$(cmtext).val(''); // remove the value from the input
console.log(json); // log the returned json to the console
$(talkid).prepend(
"<div class='col-1 p-0'><form' id=upvote' method='POST'>{%"csrf_token"%}<button
class='btn btn-md btn-outline-danger btn-
block p-auto' id='btnid' onclick='---' type='submit'></button></form></div>");
console.log("success"); // sanity check
},
// handle a non-successful response
error : function(xhr,errmsg,err) {
}
});
};
pretending my form here
<div class="row m-0" id="talk{{post.id}}"></div>
is there any other way around?
Use
{% csrf_token %}
just before the form tag inside your template.
<form id="login_frm" method="post" action = "/login/user_auth/">
<fieldset>
<legend>Login:</legend>
<label for="id_email">Email</label>
<input type="text" name="email" id="id_email" />
<label for="id_password">Password</label>
<input type="password" name="password" id="id_password" />
</fieldset>
<input name = "login" type="submit" value="Login" />
</form>
$(document).ready(function () {
$('#login_frm').submit(function() {
var $form = $(this);
$.post('/login/user_auth/' , form.serialize(), function(data) {
// alert ("function");
alert (data);
});
return false;
});
});
Django View:
def login_user(request):
if request.method == 'POST':
# perform all logic / and db access
data = "hello"
return HttpResponse(data)
# return HttpResponse ('success.html')
I have been stuck on this all afternoon.
When I return data as my response, for some reason, the browser displays "Hello" by loading a blank webpage with just "Hello" written on it; in the JavaScript function above, alert (data); is never called (I cannot understand why).
I am unable to render the success.html. I believe that if I write render_to_response inside the HttpResponse, I will solve this problem. However I think making point 1 work is a first priority.
Goal
After the post, I would like to capture the returned response from the server (whether it is just the "hello" message, or a webpage that displays a success message- stored in "success.html") and display it in place of the login_frm without having the browser refresh a new webpage.
Interesting. form is undefined (you defined it as $form) and changing to $form fixed the problem.
$(document).ready(function () {
$('#login_frm').submit(function() {
var $form = $(this);
$.post('/login/user_auth/' , $form.serialize(), function(data) {
// alert ("function");
alert (data);
});
return false;
});
});
You might want to use something like event.preventDefault() so that future errors are not hidden from you like this. $('form').submit(function(e){ e.preventDefault(); .....})