I am trying to submit a form using ajax to django view but without jquery, and i am not able to get through few things.
I am unable to send formData to django via ajax
Also unable to check if the request is made via ajax or not (request.is_ajax())
I am using core Javascript for this functionality so any help will be appreciated.
Views.py
def register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
if request.is_ajax():
# form is submited via ajax
else:
# error submitting the form via ajax
else:
return JsonResponse({'error':'There was an error'})
else:
form = RegisterForm()
context = {
'form' : form
}
return render(request, 'users/register.html', context)
AJAX
function _(e){
return document.getElementById(e);
};
function getCookie(name){
var cookieValue = null;
if(document.cookie){
var cookies = document.cookie.split(';');
for(var i = 0; i < cookies.length; i++){
cookie = cookies[i].trim();
if(cookie.substring(0, name.length + 1) == (name + '=')){
cookieValue = decodeURIComponent(cookie.substring(name.length+1));
break;
};
};
};
return cookieValue;
};
var btn = _('formBtn');
btn.addEventListener('click', function(e){
e.preventDefault();
var ajax = new XMLHttpRequest();
var fname = _('id_first_name').value;
var lname = _('id_last_name').value;
var email = _('id_email').value;
var password = _('id_password').value;
var csrfCookie = getCookie('csrftoken');
// formData not working
ajax.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
console.log(this.responseText);
}
};
ajax.open('POST', '/users/registerAjax/', true);
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajax.setRequestHeader("X-CSRFToken", csrfCookie);
ajax.send(encodeURI('first_name='+fname+'&last_name='+lname+'&email='+email+'&password='+password));
})
Related
I am making a blogging application with Laravel 8 and Bootstrap 5. It has a user profile management system.
I want to enable every user to add and delete her/his avatar. For this purpose, I have a deleteavatar() method in my UserController controller:
public function deleteavatar($id, $fileName)
{
$current_user = Auth::user();
$current_user->avatar = "default.png";
$current_user->save();
if (File::exists(public_path('images/avatars/' . $fileName))) {
File::delete(public_path('images/avatars/' . $fileName));
}
}
In the routes file:
Route::group(['prefix' => 'user'], function() {
Route::get('/', [UserController::class, 'index'])->name('user');
Route::match(['get', 'post'],'/update', [UserController::class, 'update'])->name('user.update');
Route::post('/deleteavatar/{id}/{fileName}', [UserController::class, 'deleteavatar'])->name('user.deleteavatar');
});
I use this piece of JavaScript to call the above method:
function deleteAvatar(e) {
e.preventDefault();
var avatar = document.querySelector('#avatar-container img');
var topAvatar = document.querySelector('#top_avatar');
var trashIcon = e.currentTarget;
var defaultAvatar = APP_URL + '/images/avatars/default.png';
//Get user's ID
var id = trashIcon.dataset.uid;
var fileName = avatar.getAttribute('src').split('/').reverse()[0];
var url = APP_URL + `/dashboard/user/deleteavatar/${id}/${fileName}`;
if (confirm('Delete the avatar?')) {
var CSRF_TOKEN = document.querySelectorAll('meta[name="csrf-token"]')[0].getAttribute('content');
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
avatar.setAttribute('src', defaultAvatar);
topAvatar.setAttribute('src', defaultAvatar);
trashIcon.remove();
}
}
}
xmlhttp.open('POST', url, true);
xmlhttp.send();
}
}
document.querySelector('#delete-avatar').addEventListener('click', deleteAvatar);
The problem
For a reason I have been unable to find out, the Chrome console throws this 419 (unknown status).
What is my mistake?
set xmlhttp header for csrf token
function deleteAvatar(e) {
e.preventDefault();
var avatar = document.querySelector('#avatar-container img');
var topAvatar = document.querySelector('#top_avatar');
var trashIcon = e.currentTarget;
var defaultAvatar = APP_URL + '/images/avatars/default.png';
//Get user's ID
var id = trashIcon.dataset.uid;
var fileName = avatar.getAttribute('src').split('/').reverse()[0];
var url = APP_URL + `/dashboard/user/deleteavatar/${id}/${fileName}`;
if (confirm('Delete the avatar?')) {
var CSRF_TOKEN = document.querySelectorAll('meta[name="csrf-token"]')[0].getAttribute('content');
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
avatar.setAttribute('src', defaultAvatar);
topAvatar.setAttribute('src', defaultAvatar);
trashIcon.remove();
}
}
}
xmlhttp.open('POST', url, true);
xmlhttp.setRequestHeader("X-CSRF-TOKEN", CSRF_TOKEN);
xmlhttp.send();
}
}
document.querySelector('#delete-avatar').addEventListener('click', deleteAvatar);
Ref:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader
Ref: https://laravel.com/docs/9.x/csrf
Laravel is returning http status 419 because of missing csrf token. Add the csrf token in a HTML meta tag and add to your ajax request header as well.
For reference: https://laravel.com/docs/8.x/csrf#csrf-x-csrf-token
I use in my study project django rest framework.I get an error 403 Forbidden (CSRF token missing or incorrect, when I try to save using the POST method. Here is my code html
<form id = "product_form" method = "post">
{% csrf_token %}
<input type = "hidden" name = "id" id = "id">
<p>Назвние:<input name = "name" id = "name"></p>
<p><input type = "reset" value = "Oчистить"></p>
<input type = "submit" value = "Сохранить">
</form>
Here is my code js:
let productUpdater = new XMLHttpRequest();
productUpdater.addEventListener('readystatechange', () => {
if (productUpdater.readyState == 4) {
if ((productUpdater.status == 200) || (productUpdater.status == 201)) {
listLoad();
name.form.reset();
id.value = '';
} else {
window.alert(productUpdater.statusText)
}
}
}
);
name.form.addEventListener('submit', (evt) => {
evt.preventDefault();
// let vid = id.value, url, method;
let vid = id.value;
if (vid) {
url = 'http://127.0.0.1:8000/books/api_category/' + vid + '/';
method = 'PUT';
} else {
url = 'http://127.0.0.1:8000/books/api_category/';
method = 'POST';
}
let data = JSON.stringify({id: vid,nameCategory: name.value});
productUpdater.open(method, url, true);
productUpdater.setRequestHeader('Content-Type', 'application/json');
productUpdater.send(data);
})
Here is my views.py:
#api_view(['GET', 'POST'])
def api_products(request):
if request.method == 'GET':
productsAll = CategoryMaskarad.objects.all()
serializer = CategorySerializer(productsAll, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def api_rubric_detail(request, pk):
product = CategoryMaskarad.objects.get(pk=pk)
if request.method == 'GET':
serializer = CategorySerializer(product)
return Response(serializer.data)
elif request.method == 'PUT' or request.method == 'PATCH':
serializer = CategorySerializer(product, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
product.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
Here is my urls.py:
path('api_category/<int:pk>/', api_rubric_detail),
path('api_products/', api_products),
path('api/drf-auth/', include('rest_framework.urls'))
I added the last path and logged in. In the api interface it became possible to add to the api using the post method, but with the help of js in my html I cant add data.Help me, please
I have this option. He is work.I added to js file:
name.form.addEventListener('submit', (evt) => {
evt.preventDefault();
// let vid = id.value, url, method;
let vid = id.value, url, method;
if (vid) {
url = 'http://127.0.0.1:8000/books/api_category/' + vid + '/';
method = 'PUT';
} else {
url = 'http://127.0.0.1:8000/books/api_category/';
method = 'POST';
}
let data = JSON.stringify({id: vid, nameCategory: name.value});
productUpdater.open(method, url, true);
productUpdater.setRequestHeader('Content-Type', 'application/json');
productUpdater.setRequestHeader('X-CSRFToken', csrftoken);
productUpdater.send(data);
})
and I added to html file:
<script>
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
</script>
when passing data in form to a django rest framework, you do not add the csrf_token tag before forms, rather you pass it as a header when sending api post on your endpoint.
Add this line after
try adding this function into your codes to get the values of csrftoken
let 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 = cookies[i].trim();
if(cookie.substring(0, name.length+1)===(name+'=')){
cookieValue = decodeURIComponent(cookie.substring(name.length+1));
break;
}
}
}
return cookieValue;
}
and then change the value you use in x-csrf-token and make it
productUpdater.setRequestHeader('Content-Type', 'application/json');
productUpdater.setRequestHeader('X-CSRF-Token', getCookie("csrftoken"));
I have a web site that respect a RESTful service, in html page called signup.html where the user can sign up in web site. I would redirect the user in the home page of site after the sign up is complete. How do I wait the end of XMLHttpRequest and the operations with the database from the php page associated with signup.html to redirect user in this another page?
My javascript code in signup.html is:
<script>
window.onload = bindEvents;
function bindEvents(){
//when the button with id="post" is clicked call a function userInsert
document.getElementById("post").addEventListener("click", userInsert);
}
function userInsert(){
var data = {};
data.nome = document.getElementById("nome").value;
data.cognome = document.getElementById("cognome").value;
data.nascita = document.getElementById("nascita").value;
data.email = document.getElementById("email").value;
data.password = document.getElementById("password").value;
var repassword = $("#repassword").val(); //get value of 'repeat password' to verify the correct insert
if(data.password == repassword) {
var jsondata = JSON.stringify(data);
var oReq = new XMLHttpRequest();
oReq.onload = function(){document.getElementById("ajaxres").innerHTML = oReq.responseText;};
oReq.open("post", "api_signup.php/utente/", true);
oReq.send(jsondata);
} else {
var passElem = document.getElementById("password");
var repassElem = document.getElementById("repassword");
passElem.className += " is-invalid";
repassElem.className += " is-invalid";
}
}
</script>
I would like to add a topping to my pizza using XMLHttpRequest without submitting to another page but I can't wrap my mind around how to implement it. So far I'm posting to add_topping route and getting a JsonResponse without any problem. But instead of going to the view, I would like to do it with JavaScript. I have already searched for similar problems but or they are all with PHP or with jquery but I would like to implement it using normal JavaScript with XMLHttpResponse.
HTML
<form id="add_topping" action="{% url 'orders:add_topping' %}" method="post">
{% csrf_token %}
<div class="form-row align-items-center">
<div class="form-group col-auto">
<select class="form-control" name="topping_selected" id="topping_selected">
{% for topping in topping_list %}
<option value="{{ topping }}">{{ topping }}</option>
{% endfor %}
</select>
</div>
<div class="form-group col-auto">
<button class="btn btn-secondary" type="submit">Add topping</button>
</div>
</div>
</form>
views.py
def add_topping(request):
# If request is not a POST request, return index
if request.method == 'POST':
# Get the data from the POST request
topping_selected = request.POST.get('topping_selected')
return JsonResponse({"success":True, "topping_added": topping_selected})
# Else return false
return JsonResponse({"success":False})
JavaScript
// Function to add topping
document.querySelector('#add_topping').onsubmit = function() {
// Create request object
const request = new XMLHttpRequest();
// Variables to determine the size and topping selected from the document
let topping_selected = document.querySelector('#topping_selected').value;
// Initialize the request
request.open('POST', '/add_topping', true);
// Callback function when the function completes
request.onreadystatechange() = () => {
// Extract JSON data from the request object
const data = JSON.parse(this.responseText);
console.log(data);
// Give feedback to user upon success/failure
if(data.success) {
const p = document.createElement("p");
p.innerHTML = "Topping added.";
// p.append();
// Append it to the #summary_before_add_to_cart div
document.querySelector('#summary_before_add_to_cart').append(p);
}
else {
const p = document.createElement("p");
p.innerHTML = "No topping added yet.";
// Append it to the #summary_before_add_to_cart div
document.querySelector('#summary_before_add_to_cart').append(p);
}
// Add data to send with the request
const data = new FormData();
data.append('topping_selected', topping_selected);
// Send the request
request.send(data);
// Stop submitting to another page
return false;
};
};
Thanks for any kind of help/advice. I know that this is basic stuff but I have to understand how to implement this. Thanks for your time!
here is the code that can help you do not forget to set RequestHeader as csrftoken else it will give you error
var xhr = new XMLHttpRequest();
xhr.open('POST', '{% url 'app:current_url' %}');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
console.log('Signed in as: ' + xhr.responseText);
};
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
xhr.send();
so in your case :
document.querySelector('#add_topping').onsubmit = function() {
const request = new XMLHttpRequest();
let topping_selected = document.querySelector('#topping_selected').value;
request.open('POST', '/add_topping', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.onload = function() {
const data = JSON.parse(this.responseText);
console.log(data);
if(data.success) {
const p = document.createElement("p");
p.innerHTML = "Topping added.";
document.querySelector('#summary_before_add_to_cart').append(p);
}
else {
const p = document.createElement("p");
p.innerHTML = "No topping added yet.";
document.querySelector('#summary_before_add_to_cart').append(p);
}
const data = new FormData();
data.append('topping_selected', topping_selected);
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;
}
request.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
request.send(data);
return false;
};
};
I have my JavaScript function which does XMLHttpRequest. Here is my code.
function addbilldetails() {
// Cancel the form submit
event.preventDefault();
// The URL to POST our data to
var postUrl = 'http://example.com/post.php';
// Set up an asynchronous AJAX POST request
var xhr = new XMLHttpRequest();
xhr.open('POST', postUrl, true);
// Prepare the data to be POSTed
var clientId = "clientid",
submittype = "a",
name = encodeURIComponent(document.getElementById('name').value),
billno = encodeURIComponent(document.getElementById('billno').value),
mobileno = encodeURIComponent(document.getElementById('mobileno').value),
phoneno = encodeURIComponent(document.getElementById('phoneno').value),
netAmount = encodeURIComponent(document.getElementById('netAmount').value);
var params = 'clientId=' + clientId +
'&billno=' + billno +
'&mobileno=' + mobileno +
'&phoneno=' + phoneno +
'&netAmount=' + netAmount +
'&type=' + submittype +
'&name=' + name;
// Replace any instances of the URLEncoded space char with +
params = params.replace(/%20/g, '+');
// Set correct header for form data
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// Handle request state change events
xhr.onreadystatechange = function() {
// If the request completed
if (xhr.readyState == 4) {
statusDisplay.innerHTML = '';
if (xhr.status == 200) {
// If it was a success, close the popup after a short delay
statusDisplay.innerHTML = 'Saved!';
document.getElementById('save').disabled = false;
// window.setTimeout(window.close, 1000);
} else {
// Show what went wrong
statusDisplay.innerHTML = 'Error saving: ' + xhr.statusText;
}
}
};
// Send the request and set status
xhr.send(params);
statusDisplay.innerHTML = 'Saving...';
document.getElementById('save').disabled = true;
}
Now, the above code works perfectly and returns 200 on POST. But I want it to return custom message on the UI based on the value posted.
If the value POSTed is less than the value in the database, I want it to give "Enter Valid number" or something like this.
I am quiet new to XMLHttpRequest . I do not know how to achieve that. Any help would be highly appreciated.
Instead of statusDisplay.innerHTML = 'Saved!'; have you considered:
statusDisplay.innerHTML = xhr.responseText;
If you do this, then your statusDisplay will be equal to whatever your post.php echos out.
For example, in post.php
<?php
//handling $_POST['clientId'] ... etc
if (error)
echo "Enter Valid Number";
else
echo "Saved!";