Django - How to Insert Multiple Form Data using JQuery Ajax - python

I want to perform a similar task like what described in the following video,
https://youtu.be/NoAdMtqtrTA?t=2156
To add multiple rows in the table and then insert it all in a batch to the database.
Any reference or any sample code will be really appreciable. Thank you.

The Javascript code is :
<script>
var data_dict = [];
// function called when Add row button is clicked
function Add_input_row()
{
var input_row ='<tr id="input_row">\
<td><input id="input1"></td>\
<td><input id="input2"></td>\
<td><button onclick="save_row()">save</button></td>\
</tr>';
var table_element = document.getElementById("data_table");
//do nothing if input_row already exists
if(document.getElementById("input_row")) {
alert("input row already exists !");
}
else {
table_element.innerHTML = table_element.innerHTML + input_row;
}
}
// function called when Save button is clicked
function save_row()
{
var field_val1 = document.getElementById("input1").value;
var field_val2 = document.getElementById("input2").value;
//unique id for each added data row needed when reading data directly from table
var data_id = data_dict.length;
//push the data to data dictionary
data_dict.push({
key: data_id,
value: [field_val1,field_val2]
});
var data_row ='<tr>\
<td id="data_field1'+data_id+'">'+field_val1+'</td>\
<td id="data_field2'+data_id+'">'+field_val2+'</td>\
<td></td>\
</tr>';
// remove input row
document.getElementById("input_row").remove();
//append data to table
var table_element = document.getElementById("data_table");
table_element.innerHTML = table_element.innerHTML + data_row;
}
// send data to django views
function update_database() {
var csrf_token = 'your_csrf_token';
$.ajax({
method: 'POST',
url: 'update_database', // name of your djnago view
data: {"datatobeupdated":data_dict,"csrfmiddlewaretoken" : csrf_token},
success: function (response) {
//when executed succesfully empty the data_dict and table
data_dict = [];
var table_element = document.getElementById("data_table");
table_element.innerHTML = "";
},
error: function (response) {
alert("Something Went Wrong");
}
});
}
The Html table is :
<table>
<thead>
<tr><th title="Field #1">Field1</th>
<th title="Field #2">Field2</th>
</tr>
</thead>
<tbody id="data_table">
</tbody>
</table>
<button onclick="Add_input_row()">Add row</button>
<button onclick="Update()">Update</button>
You can access the data in your django view like :
def update_database(request):
if request.is_ajax():
request_data = request.POST
## data dictionary received
datatobeupdated = request_data['datatobeupdated']

Related

Django - How to obtain corresponding row values from el-table after performing row-click?

I created a table in Django where upon doing row-click, the records for the corresponding row should be POSTED to the function "medicineRequestSelect" in view_doctor.py. However, it is unable to extract that row of values as shown in Image 1. It returns me None values.
I am relatively new to web development and any help or advice will be greatly appreciated!
<doctor_emr.html>
{% block mainbody%}
{% verbatim %}
<div id="app2" class="container">
<div class="emr-table">
<el-table
ref="multipleTable"
:data="list"
stripe
style="width: 50%"
#row-click="handle"
#selection-change="handleSelectionChange">
<el-table-column
prop="id"
label="Index">
</el-table-column>
<el-table-column
prop="order_id"
label="Order ID">
</el-table-column>
<el-table-column
prop="ward_number"
label="Ward No.">
</el-table-column>
<el-table-column
prop="prop"
label="Scan QR"
width="width">
<template slot-scope="{row$index}">
<el-button #click="onScanQR(row)" type="warning" icon="el-icon-camera" size="mini">Scan</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
{% endverbatim %}
<script>
new Vue({
el: '#app2',
data() {
return {
list: []
}
},
mounted() {
this.getemrList()
},
methods: {
getemrList() {
// Obtain EMR list
axios.post(ToDJ('emrList'), new URLSearchParams()).then(res => {
if (res.data.code === 0) {
console.log(res.data.data)
this.list = res.data.data
} else {
this.NotifyFail(res.data.data)
}
})
},
// Purpose: For the row click
handle(row, event, column) {
console.log(row, event, column)
axios.post(ToDJ('medicineRequestSelect'), new URLSearchParams()).then(res => {
if (res.data.code === 0) {
console.log(res.data.data)
this.list = res.data.data
let index = this.list.findIndex(item => {
return item.id == row.id
})
if (index == -1) {
this.$refs.multipleTable.toggleRowSelection(row, true);
this.list.push(row)
} else {
this.$refs.multipleTable.toggleRowSelection(row, false);
this.list.splice(index, 1)
}
} else {
this.NotifyFail(res.data.data)
}
})
},
onScanQR(row) {
this.dialogFormVisible = true;
this.tmForm={...row}
},
// Success notification
NotifySuc(str) {
this.$message({
message: str,
type: 'success'
})
},
// Error notification
NotifyFail(str) {
this.$message({
message: str,
type: 'warning'
})
}
}
})
</script>
{% endblock %}
<view_doctor.py>
#api_view(['GET',"POST"])
def medicineRequestSelect(request):
id = request.POST.get('id')
order_id = request.POST.get('order_id')
ward_number = request.POST.get('ward_number')
print("Values: ", id, order_id, ward_number)
return Action.success()
Image 1: Output Obtained
Image 2: Table I created
I'm also learning, and I try to progress by trying to help other's problem.
First where are you getting your data's from? From your Models?
So if I understood correctly you should import the model you want your data from and then make queries to it using your model.
model = TheNameOfYourModel.objects.all()
and then you can make your queries using q
PS: I'm still learning, i'm curious to see the answer of someone experienced

Problem dealing with a space when moving JSON to Python

I am high school math teacher who is teaching myself programming. My apologies in advance if I don't phrase some of this correctly.
I am collecting CSV data from the user and trying to move it to a SQLite database via Python.
Everything works fine unless one of the values has a space in it.
For example, here is part of my JavaScript object:
Firstname: "Bruce"
Grade: ""
Lastname: "Wayne Jr"
Nickname: ""
Here is the corresponding piece after applying JSON.stringify:
{"Firstname":"Bruce","Lastname":"Wayne Jr","Nickname":"","Grade":""}
This is then passed to Python via a form. In Python, I use:
data = request.form.get("data")
print(data)
data2 = json.loads(data)
print(data2)
I get a bunch of error messages, ending with: json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 250 (char 249) and the log of the first print gives:
[{"Firstname":"Jason","Lastname":"Bourne","Nickname":"","Grade":"10"},
{"Firstname":"Steve","Lastname":"McGarret","Nickname":"5-0","Grade":""},
{"Firstname":"Danny","Lastname":"Williams","Nickname":"Dano","Grade":"12"},
{"Firstname":"Bruce","Lastname":"Wayne
So it seems to break on the space in "Wayne Jr".
I used what I learned here to build the basics:
https://bl.ocks.org/HarryStevens/0ce529b9b5e4ea17f8db25324423818f
I believe this JavaScript function is parsing the user data:
function changeDataFromField(cb){
var arr = [];
$('#enter-data-field').val().replace( /\n/g, "^^^xyz" ).split( "^^^xyz" ).forEach(function(d){
arr.push(d.replace( /\t/g, "^^^xyz" ).split( "^^^xyz" ))
});
cb(csvToJson(arr));
}
Updates based on comments:
I am using a POST request. No AJAX.
There are actually 2 inputs for the user. A text box where they can paste CSV data and a file upload option. Here is some more of the JavaScript.
// Use the HTML5 File API to read the CSV
function changeDataFromUpload(evt, cb){
if (!browserSupportFileUpload()) {
console.error("The File APIs are not fully supported in this browser!");
} else {
var data = null;
var file = evt.target.files[0];
var fileName = file.name;
$("#filename").html(fileName);
if (file !== "") {
var reader = new FileReader();
reader.onload = function(event) {
var csvData = event.target.result;
var parsed = Papa.parse(csvData);
cb(csvToJson(parsed.data));
};
reader.onerror = function() {
console.error("Unable to read " + file.fileName);
};
}
reader.readAsText(file);
$("#update-data-from-file")[0].value = "";
}
}
// Method that checks that the browser supports the HTML5 File API
function browserSupportFileUpload() {
var isCompatible = false;
if (window.File && window.FileReader && window.FileList && window.Blob) {
isCompatible = true;
}
return isCompatible;
}
// Parse the CSV input into JSON
function csvToJson(data) {
var cols = ["Firstname","Lastname","Nickname","Grade"];
var out = [];
for (var i = 0; i < data.length; i++){
var obj = {};
var row = data[i];
cols.forEach(function(col, index){
if (row[index]) {
obj[col] = row[index];
}
else {
obj[col] = "";
}
});
out.push(obj);
}
return out;
}
// Produces table for user to check appearance of data and button to complete upload
function makeTable(data) {
console.log(data);
send_data = JSON.stringify(data);
console.log(send_data);
var table_data = '<table style="table-layout: fixed; width: 100%" class="table table-striped">';
table_data += '<th>First name</th><th>Last name</th><th>Nickname</th><th>Grade</th>'
for(var count = 0; count < data.length; count++) {
table_data += '<tr>';
table_data += '<td>'+data[count]['Firstname']+'</td>';
table_data += '<td>'+data[count]['Lastname']+'</td>';
table_data += '<td>'+data[count]['Nickname']+'</td>';
table_data += '<td>'+data[count]['Grade']+'</td>';
table_data += '</tr>';
}
table_data += '</table>';
table_data += '<p><form action="/uploaded" method="post">';
table_data += 'Does the data look OK? If so, click to upload. ';
table_data += '<button class="btn btn-primary" type="submit">Upload</button><p>';
table_data += '<input type="hidden" id="data" name="data" value='+send_data+'>';
table_data += '<input type="hidden" name="class_id" value="{{ class_id }}">';
table_data += '</form>';
table_data += 'Otherwise, fix the file and reload.';
document.getElementById("result_table").innerHTML = table_data;
}
</script>
The JavaScript can be made a lot simpler. If you do the following instead, do you have any problems with the JSON getting cut off?
document.getElementById('update-data-from-file').addEventListener('change', function(evt){
var file = evt.target.files[0];
document.getElementById('filename').innerText = file.name
if (file === "")
return;
Papa.parse(file, {
header: true,
skipEmptyLines: true,
complete: function(results) {
json = results.data
console.log(json)
// Do stuff with the json here
}
});
document.getElementById('update-data-from-file').value = ''
})
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.0.2/papaparse.min.js"></script>
</head>
<body>
<label>
Upload CSV
<input type="file" name="File Upload" id="update-data-from-file" accept=".csv" />
</label>
<div id="filename">No file chosen</div>
</body>
</html>
The problem was the way I was sending the JSON string -- it wasn't in quotes so anytime there was a space in a value, there was a problem.
To fix it: I got the JSON from the answer above, then before sending the JSON string via a POST request, I enclosed it in quotes.
send_data = JSON.stringify(json);
send_data = "'" + send_data + "'";
I am now able to send values that have spaces in it.

Jquery adding json data to html table

I need to retrieve some data from MySQL database using Flask application and post it to the HTML table using Jquery.
Here is my python code:
#app.route('/getTerm')
def getTerm():
try:
if session.get('user'):
_userID = session.get('user')
conn = mysql.connect()
cursor = conn.cursor()
cursor.execute("SELECT * FROM terms")
conn.commit()
terms = cursor.fetchall()
terms_dict = []
for item in terms:
item_dict = {
'Id': item[0],
'Name': item[3],
'Definition': item[2],
'Status': item[1],
'User': item[4]}
terms_dict.append(item_dict)
return json.dumps(terms_dict)
else:
return render_template('error.html', error = 'Unauthorized Access')
except Exception as e:
return render_template('error.html', error = str(e))
finally:
cursor.close()
conn.close()
Here is JS and HTML:
<script>
$(function(){
$.ajax({
url : '/getTerm',
type : 'GET',
success: function(res){
var tr = $('<tr>')
.append($('<td>')
.attr('class', 'name'),
$('<td>')
.attr('class', 'definition'),
$('<td>')
.attr('class', 'user'),
$('<td>')
.attr('class', 'status'));
var termObj = JSON.parse(res);
var term = '';
var td = $('<td>')
$.each(termObj, function(index, value){
term = $(tr).clone();
$(term).find('td').text(value.Name);
$(term).find('td').text(value.Definition);
$(term).find('td').text(value.User);
$(term).find('td').text(value.Status);
$('.terms').append(term);
});
},
error: function(error){
console.log(error);
}
});
});
</script>
<div class="main-terms">
<div class="main-terms_buttons">
<button>Add term</button>
<button>Assigned to me</button>
</div>
<div class="main-terms-table">
<table class="terms">
<tr>
<th>Term</th>
<th>Definition</th>
<th>Assigned to</th>
<th>Status</th>
</tr>
</table>
</div>
</div>
However in the web page I get the table where the value for 'status' is displayed in all cells. Could you please suggest what is wrong with my code?
In your jquery code you are appending all td at onces and you have use .find('td') without any other selector so that's why its targetting all tds and changing values.
Instead target only td where you need to add values i.e :
//add to required tds using class..
$(term).find('td.name').text(value.Name);
$(term).find('td.definition').text(value.Definition);
$(term).find('td.user').text(value.User);
$(term).find('td.status').text(value.Status);
$('.terms').append(term);

sending checkbox array from js to django views

I'm confused about how to do it via Ajax or Json, but how can I send the selection array (curCheck) on-click to Django views and receive it as a python array
javascript
document.getElementById('results').addEventListener('click', function(){
html_table = '<thead><tr><th>Currency</th><th>Amount</th><th>Symbol</th>><tr/><thead/>'
var checkElements = document.getElementsByClassName('ch');
for(var i =0; i< curname.length; i++){
if (checkElements[i].checked) {
var curChecked = curname[i];
var JsonArr = JSON.stringify(curChecked);
postcurChecked(JsonArr)
html_table += '<tr><td>' + curname[i] + '</td>';
}
}
document.getElementById('result_table').innerHTML = html_table;
},false;
ajax
function postsubChecked(curChecked) {
$.ajax({
"url": "http://127.0.0.1:8000/results/",
"type": "POST",
"data": {"checkbox": curChecked},
"headers": { 'X-CSRFToken': getCookie('csrftoken')}
})
}
in django
def currencyChecked(request):
body_unicode = request.body.decode('utf-8')
body_unicode = body_unicode.replace('%22','')
print(body_unicode) json_data = json.loads(body_unicode.read())
I would like to see the python array print to see it is passed to the back
but I keep getting this error:
json_data = json.loads(body_unicode.read()) AttributeError: 'str' object has no attribute 'read'
For getting the selected checkbox values and sending as an array using ajax you can use jquery like this:
consider you have multiple checkboxes and a button.
<input type="checkbox" name="imageName">
<input type="checkbox" name="imageName">
.......
<button id="deletePhoto">Delete</button>
after selecting multiple checkbox values click on this button. On clicking the below jquery will be triggered to make an arrya of selected checkbox values.
//jquery for getting the selelcted checkbox values
$(document).on("click","#deletePhoto",function(){
var favorite = [];//define array
$.each($("input[name='imageName']:checked"), function(){
favorite.push($(this).val());
});
alert("Photo Selected: " + favorite.join(", "));
if(favorite.length == 0){
alert("Select Photo to delete");
return false;
}
//ajax for deleting the multiple selelcted photos
$.ajax({type: "GET",
url: "/olx/deletePhotoFromEdit",
data:{
favorite:favorite
},
success: function(){
// put more stuff here as per your requirement
});
}
});
});
In the view you can get the array like this:
selected_photo = request.GET.getlist('favorite[]')

Paginate through json data with Flask

I am using flask and generate tables that are filled with the JSON data that I retrieve. The problem that I have now is that I need to paginate through all the JSON data, because the maximum per page is set at '50'and I want to show all the products in my table.
So far I can't get this working and I don't really know how to get it working with Flask. I tried using a while loop, but that doesn't work with Jinja2 because that command is not recognized.
This is my Python code:
#app.route('/products',methods = ['POST', 'GET'])
def products():
shopnaam = request.form['shopname']
username = request.form['username']
password = request.form['password']
login = 'https://'+shopnaam+'example.com'
url = 'https://'+shopnaam+'.example.com/admin/products.json'
payload = {
'login[email]': username,
'login[password]': password
}
with requests.Session() as session:
post = session.post(login, data=payload)
r = session.get(url)
parsed = json.loads(r.text)
return render_template('producten.html',parsed = parsed)
This is my Jinja2 code:
<button class="collapsible">Bekijk product Informatie</button>
<div class="content">
<table id = "productentabel">
<tr class = "header">
<th>ID</th>
<th>Titel </th>
<th>Prijs Exclusief BTW</th>
<th>Prijs Inclusief BTW</th>
<th>Datum</th>
{% for product in parsed['products'] %}
<TR>
<TD width="100px" >{{product['id']}}</TD>
<TD width="300px" >{{product['nl']['title']}}</TD>
<TD width="150px">{{product['price_excl']}}</TD>
<TD width="150px">{{product['price_incl']}}</TD>
<TD width="300px">{{product['created_at']}}</TD>
</TR>
</tr>
{% endfor %}
</table>
<input class = "exportknop" value="Exporteer product informatie" type="button" onclick="$('#productentabel').table2CSV({header:['ID','Titel','Prijs Exclusief BTW', 'Prijs Inclusief BTW', 'Datum']})">
</div>
As you can see I am using a for loop, this code works, but the pagination is the issue.
My JSON looks like this:
products: [
{
article_code: "123",
barcode: "456",
brand_id: 2600822,
created_at: "2018-05-31T15:15:34+02:00",
data01: "",
data02: "",
data03: "",
delivery_date_id: null,
has_custom_fields: false,
has_discounts: false,
has_matrix: false,
hits: 0,
hs_code: null,
id: 72660113,
image_id: null,
is_visible: false,
price_excl: 33.0165,
price_incl: 39.95,
price_old_excl: 0,
price_old_incl: 0,
product_set_id: null,
product_type_id: null,
search_context: "123 456 789",
shop_id: 252449,
sku: "789",
supplier_id: 555236,
updated_at: "2018-05-31T15:15:34+02:00",
variants_count: 1,
visibility: "hidden",
weight: 0,
links: {
first: ".json",
last: ".json?page=70",
prev: null,
next: ".json?page=2",
count: 3497,
limit: 50,
pages: 70
}
So links is where the pagination happens, I tried the following in my Python code and with this I get all the values printed in my python terminal. Only I can't send the data to the tables.
while url:
with requests.Session() as session:
post = session.post(login, data=payload)
r = session.get(url)
parsed = json.loads(r.text)
for product in parsed['products']:
print(product['id'], product['nl']['title'])
url = 'https://example/admin/products' + parsed['links']['next']
So a couple things to consider here. First, using a generator to create web content is going to be next to impossible outside of a websocket or async calls. The reason is that WSGI needs all the data to come before it renders. Then it closes the connection. You can yield data, but in a table, this is going to cause problems in raw html.
What to do:
I would use something like datatables (datatables.net) feed your table data into a variable, and let datatables handle the pagination for you.
Example using Bootstrap 4 and DataTables.
<script>
var dataSet = []
var wurl = ""
tablex = $('#tablex').dataTable( {
select: true,
stateSave: true,
colReorder: true,
deferRender: true,
"oLanguage": {"sSearch": "Filter:"},
columns: [
{ title: "Number" },
{ title: "Client Name" },
{ title: "Opened" },
{ title: "Closed" },
{ title: "Worked" }
]
} );
function generate() {
$.get(wurl, function( data ) {
dataSet = data;
tablex.fnDestroy();
tablex = $('#tablex').dataTable( {
data: dataSet,
select: true,
stateSave: true,
colReorder: true,
deferRender: true,
"oLanguage": {"sSearch": "Filter:"},
columns: [
{ title: "Number" },
{ title: "Client Name" },
{ title: "Opened"},
{ title: "Closed"},
{ title: "Worked"}
],
} );
});
};
$(document).ready(function() {
wurl = '/api/getdata';
generate()
} );
</script>
I first establish just a base table, and then I call an API and load that table with data in the background. You could even have this poll and refresh the dataset on an interval if you wanted. The API just delivers the raw data in a column output.
Your table id is "tablex" in this example.
Your API route can be anything, just a return value of your output that is in column and row format.

Categories