How to handle POST form data with Django (refresh avoided)? - javascript

I'm trying to save the form's data in a database using Django. Refreshing after click on submit button is avoided using:
scripts.py
var form = document.getElementById("mail_form_id");
function handleForm(event) { event.preventDefault(); }
form.addEventListener('submit', handleForm);
function send_mailform(){
console.log("cal")
var http = new XMLHttpRequest();
http.open("POST", "", true);
http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
var params = "search=" + document.getElementById('mail_input').value;
http.send(params);
http.onload = function() {
alert(http.responseText);
}
}
document.getElementById("mail_send_btn").addEventListener('click', send_mailform, false);
views.py
#Mail check
if request.POST:
Marketingform = Marketingforms(request.POST)
if Marketingform.is_valid():
receiver_mail = Marketingform.cleaned_data['receiver_mail']
p = mail_receiver(receiver_mail=receiver_mail)
p.save()
print("correct")
views.py
class mailForm(forms.ModelForm):
class Meta:
model = mail_receiver
fields =[
'receiver_mail',
]
widgets = {
'receiver_mail': forms.EmailInput(attrs={ 'id':'mail_input', 'name':'mail_input'}),
}
How can I receive the value of params in the django views.py?

First your ajax request is not going to work because of csrf token. you must have a request header with name: 'X-CSRFToken' and value of the csrftoken cookie that is in the browser cookies. You must get the csrftoken cookie value and set as the header value.
Header should look like:
http.setRequestHeader('X-CSRFToken', getCookie('csrftoken'));
And getCookie() must be function to get cookie value based on its name. Django has a clean doc about this: https://docs.djangoproject.com/en/3.0/ref/csrf/
And the answer for your question is that request object contains the post data and you can have them like:
request.POST.get('param_name')
This will return None if param_name doesn't exists.
Also its better to check like:
if request.is_ajax():instead of if request.POST:

Related

django form.is_valid returns false when while using XMLHttpRequest

since bootstrap 5 no longer ships with jquery and recommends using the vanilla javascript XMLHttpRequest() to make dynamic requests that is what I am trying to do in django. All the other examples of doing this use the traditional .$ajax.
I have a basic javascript function:
function sendPhoneVerification(_phone) {
var http = new XMLHttpRequest();
const params = {
phone: _phone
}
http.open('POST', '/approvephone/', true)
http.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
http.setRequestHeader('Content-type', 'application/json')
http.setRequestHeader('phone', _phone)
http.send(JSON.stringify(params))
http.onload = function() {
alert(http.responseText)
}
}
The CSRF middlware token is working fine, but the in the view, the form.is_valid() returns false and the error is that required field "phone" is missing. I can't tell how I am supposed to provide that value. The form being tested against is a simple form with one field
class AddPhoneForm(forms.Form):
phone = PhoneNumberField()
relevant part of the view
#csrf_protect
#login_required
def approvephone(request):
if request.method == 'POST':
form = AddPhoneForm(request.POST)
if form.is_valid() #returns false and error is missing field "phone"
Any idea how I can correctly provide the phone fields in the POST response to make django happy?
ok I feel stupid, but in django you need to send 'Content-type', 'application/x-www-form-urlencoded' as described here
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send
function sendPhoneVerification(_phone) {
alert("Hello! I am an alert box!!" + _phone);
var http = new XMLHttpRequest();
http.open('POST', '/approvephone/', true)
http.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
http.send("phone="+_phone)
http.onload = function() {
alert(http.responseText)
}

How to fixed 419 unknown status in XMLHttpRequest?

I have an error in my XMLHttpRequest() when sending a post request to my url. When I check my console.log it says
this line of code:
xhr.send();
Error: Failed to load resource: the server responded with a status of 419 (unknown status)
Here's my script code using only pure javascript:
<!-- Get Parameters for gclid or token when user visits the website -->
<script>
window.onload = function() {
try {
var url_string = (window.location.href).toLowerCase();
var url = new URL(url_string);
// Get Gclid
var token = url.searchParams.get("gclid");
// gclid expires in 6 hours
document.cookie = `gclid=${gclid}; max-age=21600`;
// Sending a get request to laravel controller
var base_url = window.location.origin; // get the base url
var params = "gclid=" + gclid;
let xhr = new XMLHttpRequest();
xhr.open("POST", base_url+"/storetrackvisit?"+params, true);
xhr.send();
} catch (err) {
console.log("Issues with Parsing URL Parameter's - " + err);
}
}
</script>
I'm trying to pass parameters in this XMLHttpRequest() so that when users has this parameters.
Example:
https://www.test.com/?gclid=312
It will send a post request to my storetrackvisit page along with the parameters and save it to db:
https://www.test.com/storetrackvisit?gclid=312
let xhr = new XMLHttpRequest();
xhr.open("POST", base_url+"/storetrackvisit?"+params, true);
xhr.send();
so that it will save to my controller like this:
TrafficController
public function storeParams(Request $request)
{
$traffic = new TrafficTracking();
if ($request->has('gclid')) { // check if key = gclid
$traffic->traffic_type = 'gclid'; // store the key in db
$traffic->traffic_value = $request->gclid;
}
if ($traffic->value === null) {
return response()->noContent();
}
$traffic->ip_address = $request->ip();
$traffic->domain = $request->getHttpHost();
$traffic->save();
}
web.php
// Traffic Controller
Route::post('/storetrackvisit', 'TrafficController#storeParams')->name('user.store.trackvisit');
What seems to be an error in my xhr.send(); returning a status of 419 (unknown status)?
Is it because there is no csrf token passed along with my XMLHttpRequest in javascript? If so, how do I pass it in the XMLHttpRequest or maybe what's causing the 419 (unkown status)?
Usually a 419 Error means a missing CSRF token from a request. You can handle it easily in two ways.
Change the route to GET if you're not sending any sensitive info.
Include a CSRF token in your request.
I will explain about point number 2, how can you include a CSRF token in your request.
Now, there are also two ways to include a CSRF token:
Call it in header.
Create a HTML input field containing token.
1. Call it in Headers
You can define CSRF token in your header like this,
<meta name="csrf-token" content="{{ csrf_token() }}">
and then access it in JavaScript and set headers for it like this,
xhr.setRequestHeader(header, value);
2. Create a HTML input field containing token
You can create an input field containg token like this,
<!-- It's a laravel blade directive, which creates an input field containing token -->
#csrf
<!-- or manually do it -->
<input type="hidden" name="_token" value="{{ csrf_token() }}">
Get it in your JavaScript and send it as a parameter like this,
let csrfToken = document.getElementsByName("_token");
params += "&_token=" + csrfToken;

Remove selected file(s) by clicking the remove link from the input file multiple and submit to Controller's parameter

How do I post the file(s) to the parameter in my Controller?
I have a breakpoint for my Action in my Controller and I want to see if the files (after removed some unwanted files) can be post through my Controller.
Right now, even if I hit upload button, the breakpoint will give me a null value instead of the name of the files.
After clicking the submit button, the files displayed in the Console (F12) is alright, but for the breakpoint in my Controller is showing null.
What should I do to post the files to my Controller?
Your ajax code is sending files with the name of fileList[] , but your server expects a parameter with a name of parameterIsHere and the Type should be UploadFiles.
It seems that you doesn't send a CSRF token
How to fix :
Approach A :
Server Side: change your action method as below (Note the Type and the name):
[HttpPost]
public IActionResult UploadAction(List<IFormFile> fileList)
{
// ...
}
Client Side : add CSRF token and change the name of fields to be fileList:
function sendModifiesList(e) {
e.preventDefault();
fileList.forEach(function(file,idx) {
formData.append(`fileList`, file); //// name should be `fileList`
});
formData.append("__RequestVerificationToken",$("form input[name='__RequestVerificationToken']").val());
console.log("These files will be posted: ", formData.getAll("fileList"));
/*************** EDIT *************************/
// Get the url from the form's action attribute
let url = document.forms[0].action;
let request = new XMLHttpRequest();
// Create a POST request
request.open("POST", url);
// Set up an onload handler to report status
request.onload = function() {
if (request.status == 200) {
console.log("Uploaded!");
} else {
console.log("Error " + request.status + " occurred when trying to upload your file.");
}
};
// Send the form to the server
request.send(formData);
/************ END EDIT ***********************/
};
Approach B :
if you don't care the name, you could simply use the HttpContext.Request.Form.Files to get the files:
[HttpPost]
public IActionResult UploadAction()
{
var files= HttpContext.Request.Form.Files;
// ...
}

inserting data, sent from javascript using POST, into mysql database using php

I have been trying to insert data into a table in a mysql database. This data was sent with ajax using the POST method. However, when I try to insert it into the database nothing happens.
So here is the javascript function the sends the data to the php file.
addToCart: function(itemId,userId){
let request = new XMLHttpRequest();
request.open("POST", "../E-CommerceCore/addToCart.php?
itemId="+ itemId + "?userId=" + userId, true);
request.send();
},
Here is where it is being used. This is nested in a bigger function so thats where the book[i].Id comes from.
document.getElementById('add-to-cart').onclick = function(){
cartFunctions.addToCart(book[i].Id, '1');
};
So this takes an item id and a user id and stores them in a php variables here.
class Cart
{
public function addToCart($item,$user){
include 'connect.php';
$query = $bookStore->prepare("INSERT INTO cart SET item_Id=?, user_Id=?");
$query->execute([$item,$user]);
}
}
$cartManager = Cart();
$itemId = $_REQUEST["itemId"];
$userId = $_REQUEST["userId"];
$cartManager->addToCart("$itemId","$userId");
This php file then runs the addToCart function which should insert it into the table. This is where I run into the problem because not data is inserted to the database when the user clicks the button. I use the connect.php file for another controller that selects from a different table in the same database, if that is an issue, and yes I have checked to make sure that the connection to the database is good. Any insight would be immensely appreciated. Please no jQuery solutions. Thank you for you time and effort.
request.open("POST", "../E-CommerceCore/addToCart.php? itemId="+ itemId + "?userId=" + userId, true); You are sending the parameters as GET with the url and you have another mistake since you used another ? to separate the 2 parameters . Please follow this link to send your data: Send POST data using XMLHttpRequest
var http = new XMLHttpRequest();
var url = "path_to_file.php";
var params = "itemId="+ itemId + "&userId=" + userId; //Please note that the 2 params are separated by an **&** not a **?** as in your question
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(params);
Also the quotes here are unnecessary when passing parameters:
$cartManager->addToCart("$itemId","$userId");
If it is possible try to var_dump($_REQUEST) before calling the addToCart method to make sure that parameters have been successfully sent through the javascript request.
Now regarding the sql query you have to update the class and use bindParam and afterwards call the execute. I have updated your php code as follows:
class Cart{
public function addToCart($item,$user){
include 'connect.php';
$query = $bookStore->prepare("INSERT INTO cart SET item_Id=:item_id, user_Id=:user_id");
$query->bindParam(':item_id', $item);
$query->bindParam(':user_id', $user);
$query->execute();
}
}
$cartManager = new Cart();
$itemId = $_REQUEST["itemId"];
$userId = $_REQUEST["userId"];
$cartManager->addToCart($itemId, $userId);
For more reference regarding prepared statements you can have a look at this: http://php.net/manual/en/pdo.prepared-statements.php

Submit a form obtained via XMLHttpRequest?

I am trying to a download a html page via javascript, parse it and submit the form with the following code. Everything seems to work perfectly in this function, yet I am unable to see the desired server side changes. Could someone point me if there's something wrong in this approach ?
function get_page(url){
var xhr = new XMLHttpRequest();
xhr.responseType = "document"; //parse html
xhr.open("GET", url);
xhr.send(null);
xhr.onload = function(){
// get form here
var dom = xhr.responseXML;
var form = dom.forms[0];
// set values in fields
form[0].value='hello';
form[1].value=form[0].value;
//change action from # to url
form.action = url;
//EDIT: attach form to body
document.getElementsByTagName('body')[0].appendChild(form);
//form submit
form.submit();
//print form last value
console.log(form[3].value);
}
}

Categories