how can AJAX dynamically add rows to a table - python

I was wondering if someone could help me figure out how to add rows to the following html dynamically using AJAX whenever a database query finds more records. I am using python flask and pandas to create a dataframe with nodes information such as when a node is ACTIVE, or in SLEEP mode, LOCKED or UNLOCKED. I was thinking that I could somehow pass that dataframe and iterate through it to create a table with that information and a link to another page for that specific node. Now,I think I have the first part down where I am POSTing the page when it is first brought up with all of the recorded nodes. But I think I'm doing that part wrong too. I suppose I have two questions then:
How can I pass a dataframe to the html and iterate through it correctly?
How can I use AJAX to add another row to the table whenever any other node that registers? I was thinking maybe I pass a list of nodeID's to the HTML when I POST and then have setInterval pass that to the python flask side, query the database, create a new list and compare..removing those that I already added, pass the dataframe of those that are new to AJAX function along with a full list of NodeID's....does that sound right?
So far I was only able to figure this out for a POST but no idea what to do next:
HTML
<div class="container">
<h2>Incubator List</h2>
<p>List of Registered Encubators:</p>
<table class="table table-dark table-striped">
<thead>
<tr>
<th>NodeID</th>
<th>Last Update</th>
<th>Status</th>
<th> </th>
<th>Control Link</th>
</tr>
</thead>
{% for node in nodes %}
<tr>
<td>{{ node.NodeID }}</td>
<td>{{ node.last_update }}</td>
{% if {{ node.Sleep }} == "True" %}
<td><p class="bg-secondary text-white text-center">SLEEP</p>></td>
{% else %}
{% if {{ node.Active }} == "True" %}
<td><p class="bg-success text-white text-center">ACTIVE</p></td>
{% else %}
<td><p class="bg-danger text-white text-center">NOT ACTIVE</p>></td>
{% endif %}
{% endif %}
{% if {{ node.LOCK }} == "True" %}
<i class="fas fa-lock"></i>
{% else %}
<i class="fas fa-unlock"></i>
{% endif %}
<td>
<form action="/nodeslist" METHOD = "POST">
<input type="hidden" id="NodeID" name="NodeID" value={{ node.NodeID }}>
<input TYPE="SUBMIT" value="Access" class = "btn btn-success">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script>
function UPDATEnodelist(nodeIDlist) {
$.get('/nodeDHT?nodeIDlist ='+nodeIDlist ,
function(data){
const parsed = JSON.parse(data)
nodeIDlist = parsed.nodeIDlist;
something-pandas-dataframe-something;
};
)
};
setInterval(function () {
UPDATEnodelist(nodeIDlist);
return false;
}, 2500);
</script>
{% endblock content %}
python flask
#app.route('/nodeslist', methods=['POST','GET'])
def nodelist():
df= DAO.Pull_Type_Nodes()
if request.method == "POST":
title='List of Registered Nodes')
nodeIDlist = nodes.NodeID.unique()
nodes = df.to_json(orient ='records')
return render_template('nodeslist.html',title=title, nodes=nodes, nodeIDlist=nodeIDlist)
else:
oldnodeIDlist = request.form['NodeID']
add_df = df[~df['NodeID'].isin(oldnodeIDlist)]
new_nodes = add_df.to_json(orient ='records')
return new_nodes,nodeIDlist
Please any help would be greatly appreciated!
EDIT:
The response should be a dataframe with fields 'nodeID','sleep' (bool), 'lock' (bool), 'active' (bool)

<table id="table" class="table table-dark table-striped">
<thead>
<tr>
<th>NodeID</th>
<th>Last Update</th>
<th>Status</th>
<th></th>
<th>Control Link</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<form action="/nodeslist" METHOD="POST">
<input type="hidden" id="NodeID" name="NodeID" value={{ node.NodeID }}>
<input TYPE="SUBMIT" value="Access" class="btn btn-success" id="btn">
</form>
</td>
</tr>
</tbody>
</table>
const date = new Date();
const data = [...Array(10).keys()].map(id => {
return {
id: id+1,
date: new Date((Math.random() * 10000000) + date.getTime()).toLocaleString(),
status: Math.floor(Math.random() * 2),
};
});
const tbody = document.querySelector('#table').querySelector('tbody');
function test(evt) {
evt.preventDefault();
let fragment = document.createDocumentFragment();
data.forEach(d => {
let tr = document.createElement('tr');
Object.keys(d).forEach(x => {
let td = document.createElement('td');
let textNode = document.createTextNode(d[x]);
td.appendChild(textNode);
tr.appendChild(td);
})
fragment.appendChild(tr);
});
tbody.appendChild(fragment);
}
document.querySelector('#btn').onclick = test;
Here working example

Related

How to take the value from the field and send it to the Flask code for use in the updated page

Have a good day!
I don't know much about Flask
I try to depict insert several (two) objects on the page and embed add the ability (so that you can) update these objects.
There is a main element on the page - the choice of a date range.
When you select a start date and an end date and click the button in the same way (two objects should be updated).
The first object is a table. The table (object) is updated.
The second object is a graph. This object is not updated.
What can be done to update the second object (chart)?
I would be extremely grateful for any help.
It's HTML
<div class="row">
<div class="col-md-3">
<input type="text" name="From" id="From" class="form-control" placeholder="From Date"/>
</div>
<div class="col-md-3">
<input type="text" name="to" id="to" class="form-control" placeholder="To Date"/>
</div>
<div class="col-md-6">
<input type="button" name="range" id="range" value="Range" class="btn btn-success"/>
</div>
</div>
<div id="purchase_order"></div>
<hr>
<div class="row" style="align-content: center">
<div class="text" style="align-content: center">
</div>
<div class="outer-wrapper" style="align-content: center">
<div class="table-wrapper" id="table-wrapper" style="align-content: center">
<table>
<thead>
{% for col in column_names %}
<th>{{col}}</th>
{% endfor %}
</thead>
<tbody>
{% for row in row_data %}
<tr>
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-md-1">
</div>
<div class="col-md-10">
<div>
<canvas id="myChart" width="800px" style="align-content: center"></canvas>
</div>
</div>
<div class="col-md-1">
</div>
</div>
it's script
<script>
$(document).ready(function (){
$.datepicker.setDefaults({
dateFormat: 'yy-mm-dd'
});
$(function (){
$("#From").datepicker();
$("#to").datepicker();
});
$('#range').click(function (){
var From = $('#From').val();
var to = $('#to').val();
if (From != '' && to != '')
{
$.ajax({
url:"/range",
method:"POST",
data:{From:From, to:to},
success:function (data)
{
$('#table-wrapper').html(data);
$('#table-wrapper').append(data.htmlresponse);
}
});
$.ajax({
url:"/range2",
method:"POST",
data:{From:From, to:to},
success:function (data)
{
$('#myChart').html(data);
$('#myChart').append(data.htmlresponse2);
}
});
}
else
{
alert("Please Select the Date")
}
});
});
</script>
it's Flask code
#app.route('/', methods=['GET','POST'])
#app.route('/index')
def home_page(): # put application's code here
if request.method=="POST":
upload_excel=request.files['upload_excel']
if upload_excel.filename != '':
filepath=os.path.join(app.config["UPLOAD_FOLDER"],upload_excel.filename)
upload_excel.save(filepath)
data=pd.read_excel(upload_excel)
data.to_sql('kotel', con=db.engine, if_exists="append", index=False)
return print(data)
df = pd.read_sql('select * from kotel', con=db.engine)
df['date'] = df['date'].dt.round('2min')
y_data = df['tnv'].tolist()
x_data = df['date'].tolist()
print(y_data)
type(y_data)
print(x_data)
df_graph = df.copy()
df_graph.drop(df_graph.columns[[0, 1, 2]], axis=1, inplace=True)
print(df_graph)
# df['date'] = pd.to_datetime(df['date'], format="%Y.%d.%B %H")
return render_template('index new.html', column_names=df.columns.values, row_data=list(df.values.tolist()), column_names_graph=df_graph.columns.values, os_y = y_data, os_x = x_data)
#app.route("/range", methods=["POST","GET"])
def range():
if request.method == 'POST':
From = request.form['From']
to = request.form['to']
df = pd.read_sql('select * from kotel', con=db.engine)
df['date'] = pd.to_datetime(df['date'])
df = df.loc[(df['date'] >= From) & (df['date'] <= to)]
df['date'] = df['date'].dt.round('2min')
return jsonify({'htmlresponse': render_template('response.html', column_names=df.columns.values, row_data=list(df.values.tolist()))}), df
#app.route("/range2", methods=["POST","GET"])
def range2():
df_new = pd.read_sql('select * from table_1', con=db.engine)
y_data = df_new['temper'].tolist()
x_data = df_new['rashod'].tolist()
return jsonify({'htmlresponse2': render_template('response2.html', os_y = y_data, os_x = x_data)})
it's extended html 1 add
<table>
<thead>
{% for col in column_names %}
<th>{{col}}</th>
{% endfor %}
</thead>
<tbody>
{% for row in row_data %}
<tr>
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
it's extended html 2 add
<script>
const labels = [{% for item in os_x %}
"{{ item }}",
{% endfor %}];
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [{% for item in os_y %}
{{ item }},
{% endfor %}],
}]
};
const config = {
type: 'line',
data: data,
options: {}
};
</script>
<script>
const myChart = new Chart(
document.getElementById('myChart'),
config
);
</script>
I would really like to be able (so that I can) take a value variable from a form field (dropdown ) and send it to the Flask code so that I can use it in the updated page.
image screen
image screen

AJAX unable to define the key's method in Django

First off, sorry for the odd phrasing of the title.
I currently have a webapp that allows users to order food from a resturant. In the menu html I currently have the following snippet.
{% if latest_order %}
<table class="table" id="checkout-table">
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th scope="col">YOUR</th>
<th scope="col">CART</th>
<th scope="col"></th>
</tr>
</thead>
{% for order in latest_order %}
<tr>
<td>{{ order.order_name }}</td>
<td class="change-quantity">
<form method="post">
{% csrf_token %}
<div class="row">
<div class="col-sm">
<button type="submit" name="remove_quantity" value="{{ order.id }}"
class="mr-3 btn btn-outline-info">-</button>
</div>
<div class="col-sm">
{{ order.order_quantity }}
</div>
<div class="col-sm">
<button type="submit" name="add_quantity" value="{{ order.id }}" class="ml-3 btn
btn-outline-info">+</button>
</div>
</div>
</form>
</td>
<td>${{ order.order_individual_price }}</td>
in my JS I have the following AJAX code running
$(document).ready(function(){
$(".ramen").click(function(event){
event.preventDefault()
var serializedData = $("#ramen-form").serialize()
$.ajax({
url: $("ramen-form").data("url"),
data: serializedData,
type: 'post',
success: function(response) {
$("#checkout-table").append('<tr><td>' + response.new_order.order_name + '</td><td class="change-quantity">' +
'<form method="post">{% csrf_token %}<div class="row"><div class="col-sm">' +
'<button type="submit" name="remove_quantity" value="{{ order.id }}"class="mr-3 btn btn-outline-info">-</button>' +
'</div><div class="col-sm">'+ response.new_order.order_quantity +'</div><div class="col-sm">' +
'<button type="submit" name="add_quantity" value="{{ order.id }}" class="ml-3 btn btn-outline-info">+</button>' +
'</div></div></form></td><td>$'+ response.new_order.order_individual_price +'</td><form method="post">{% csrf_token %}<th>' +
'<button type="submit" name="delete" value="{{ order.id }}" class="btn btn-danger">Delete Item</button></th></form></tr>')
}
})
});
})
In my views.py I have the following to return a JsonResponse
get_price = menu_name.Menu_price
get_desc = menu_name.Menu_Desc
new_order = Order.objects.create(
customer=request.user,
order_name=menu_name,
order_individual_price=get_price,
order_default_price=get_price,
order_desc = get_desc,
)
return JsonResponse({'new_order':model_to_dict(new_order)}, status=200)
AJAX returns the following error after I try to add an item to cart
I think the problem is you don't parse the response. So, JQuery doesn't read it becase it is a string, not JSON. You might add the following to your AJAX call to parse it automatically:
$.ajax({
...
dataType: 'json',
success: function(response) {
...
}
}
Since you're using JQuery, you might also use $.parseJSON() to parse response.

table row order are not updatin in the database after ajax call in django

I am using jquery UI .sortable to sort my table rows by drag and drop. I have declare a field map_order in the model as an order update. so the thing is when I am making ajax call to update the model order field. it didn't update it. but when I console log the sort variable it will show the assigning of index to the pk of model.
I have tried to update the filed but it did,nt work
HTML
<tbody id="#layerTable">
{% for layer in layers %} ​
<tr data-pk="{{ layer.id }}" class="ui-state-default"> <td><input type="checkbox" name="ids" value="{{ layer.id }}" /></td>
<td> {{ layer.name }} </td>
<td>{{ layer.heading }}</td>
<td>{{ layer.class_group }}</td>
<td> <span class="glyphicon glyphicon-resize-vertical"></span> {{ layer.map_order }}</td>
<td>{{ layer.map_server }} </td>
<td> {% if layer.sql_schema %}{{ layer.sql_schema }}.{{ layer.sql_table }}{% endif %} </td>
</tr>
​
JS
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$("tbody").sortable({
update: function(event, ui) {
​
sort = {};
window.CSRF_TOKEN = "{{ csrf_token }}";
$("tbody").children().each(function(){
sort[$(this).data('pk')] = $(this).index();
});
​
{#var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();#}
$.ajax({
url: "{% url "mapport.maps.layers.all" map.id %}sort/",
type: "post",
data:{sort,
csrfmiddlewaretoken: window.CSRF_TOKEN,
},
​
});
console.log(sort)
},
}).disableSelection();
});
​
</script>
views
#csrf_exempt
def sort(self):
for index, pk in enumerate(self.request.POST.getlist('layer[]')):
layer = get_object_or_404(Layer, pk=pk)
layer.map_order = index
layer.save()
​
return HttpResponse('')
I I have expected to update the field map_order.. but it didn't update. the index is assigning in browser to the id when I drag and drop rows

Create search field to sort for each column data

I am new to Django, my index page shows all projects including project_number column, project_description column and so on. I would like to have search field in every column if I search for project description, it will display project description results along with theirs project_number in the same page and vice versa. Im using ajax but it gave me an error
Internal Server Error: /polls/ajax/validate_username/
Traceback (most recent call last):
File "/home/pdinh/environments/newproject/newenv/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/home/pdinh/environments/newproject/newenv/lib/python2.7/site-packages/django/core/handlers/base.py", line 198, in _get_response
"returned None instead." % (callback.module, view_name)
ValueError: The view polls.views.validate_username didn't return an HttpResponse object. It returned None instead.
[25/Jul/2018 16:06:51] "GET /polls/ajax/validate_username/?the_post= HTTP/1.1" 500 16574
could someone give me help? everything else works properly except the ajax
below is my code
================index.html=====================
{% block body %}
<div class = "container">
<!-- <form name = "search_form" action = "{% url 'search' %}">
<input type = "text" name = "search" placeholder = "Search"></input>
<button type = "submit" style = "height: 25px; width: 90px">Search</button><br/>
</form> -->
<!-- <form name="search_form" action="{ url 'search' %}" -->
<form >
<div class = "pagination">
<table class = "table table-hover table-dark">
<tr>
<th scope = "col">No</th>
<th scope = "col">Section</th>
<th scope = "col">Project Description</th>
<th scope = "col">Project ID</th>
<th scope = "col">Employee Name</th>
<th scope = "col">Funding Year </th>
</tr>
<tr>
<!-- <form name = "search_form" action = "{ url 'search' %}"> -->
<form name = "search_form" method="GET">
{% csrf_token %}
<div id="the_post">
<th scope = "col"><input type = "text" name = "search_no" placeholder = "Search"></input></th>
<th scope = "col"><input type = "text" name = "search_section" id="id_section" placeholder = "Search"></input></th>
<th scope = "col"><input type = "text" name = "search" id = "search1" placeholder = "Search"></input><input type="submit" value="Search"></input></th>
<th scope = "col"><input type = "text" name = "search_id" placeholder = "Search"></input></th>
<th scope = "col"><input type = "text" name = "search_name" placeholder = "Search"></input></th>
<th scope = "col"><input type = "text" name = "search_year" placeholder = "Search"></input></th>
</div>
</form>
</tr>
{% if projects %}
{% for project in projects%}
<tr>
<td> {{project.pro_no}} </td>
<td scope = "row">{{project.pro_section}}</td>
<td>{{project.pro_description}}</td>
<td>{{project.pro_ID}}</td>
<td>
{% for emp in project.employee.all %}
<table>
<tr><td>{{emp.first_name}}</td></tr>
</table>
{% endfor %}
</td>
<td>
{% for emp in project.employee.all %}
<table>
<tr><td>{{emp.funding_year}}</td></tr>
</table>
{% endfor %}
</td>
</tr>
{% endfor %}
{% endif %}
<span class = "step-links">
{% if projects.has_previous %}
<i class = "fa fa-angle-double-left" style="color:black"></i>
Previous
{% endif %}
<span class = "current">
Page {{projects.number}} of {{projects.paginator.num_pages}}.
</span>
{% if projects.has_next %}
<i class="fa fa-angle-double-right" style="color:black"></i>
<a class="fa fa-angle-double-right" style="color:black" href = "?page={{projects.next_page_number}}">Next</a>
{% endif %}
<span>
</table>
{% block javascript %}
<script>
$.ajax({
url: '{% url "validate_username" %}',
type: "GET",
data: {'the_post': $("#search1").val()},
success: function(data){
$("#search1").remove('');
alert("data:")
},
});
</script>
{% endblock %}
</div>
</form>
<!-- </form> -->
</div>
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
{% endblock %}
========================VIEWS.PY============
def validate_username(request):
if request.method == "GET":
description = request.GET.get('the_post')
#response_data = {}
#response_data['pro_description'] = Project.objects.filter(pro_description__icontains = description)
data = {
'pro_description': Project.objects.filter(pro_description__icontains = description)
}
#return HttpResponse(json.dumps(response_data), content_type = "application/json")
return JsonResponse(data)
=================URLS.PY=============
url(r'^ajax/validate_username/$', views.validate_username, name = 'validate_username'),

In my Django template, how do I display the check boxes and notification types?

If this is the view in Django_notification (https://github.com/pinax/django-notification/blob/master/notification/views.py), how do I display the check box? It doesn't seem like there are form objects here. Usually, I'm used to doing this: {{ myform.thefield }}
#login_required
def notice_settings(request):
"""
The notice settings view.
Template: :template:`notification/notice_settings.html`
Context:
notice_types
A list of all :model:`notification.NoticeType` objects.
notice_settings
A dictionary containing ``column_headers`` for each ``NOTICE_MEDIA``
and ``rows`` containing a list of dictionaries: ``notice_type``, a
:model:`notification.NoticeType` object and ``cells``, a list of
tuples whose first value is suitable for use in forms and the second
value is ``True`` or ``False`` depending on a ``request.POST``
variable called ``form_label``, whose valid value is ``on``.
"""
notice_types = NoticeType.objects.all()
settings_table = []
for notice_type in notice_types:
settings_row = []
for medium_id, medium_display in NOTICE_MEDIA:
form_label = "%s_%s" % (notice_type.label, medium_id)
setting = get_notification_setting(request.user, notice_type, medium_id)
if request.method == "POST":
if request.POST.get(form_label) == "on":
if not setting.send:
setting.send = True
setting.save()
else:
if setting.send:
setting.send = False
setting.save()
settings_row.append((form_label, setting.send))
settings_table.append({"notice_type": notice_type, "cells": settings_row})
if request.method == "POST":
next_page = request.POST.get("next_page", ".")
return HttpResponseRedirect(next_page)
notice_settings = {
"column_headers": [medium_display for medium_id, medium_display in NOTICE_MEDIA],
"rows": settings_table,
}
return render_to_response("notification/notice_settings.html", {
"notice_types": notice_types,
"notice_settings": notice_settings,
}, context_instance=RequestContext(request))
The default template for this view is checked into github: https://github.com/pinax/pinax/blob/master/pinax/templates/default/notification/notice_settings.html
UPDATE: Pinax removed their themes, the last checkin with templates can still be found here.
There is no form defined for the notification settings object, so the checkbox elements (and the form itself) are created using raw HTML:
<form method="POST" action=""> {# doubt this easy to do in uni-form #}
{% csrf_token %}
<table class="notice_settings">
<tr>
<th>{% trans "Notification Type" %}</th>
{% for header in notice_settings.column_headers %}
<th>{{ header }}</th>
{% endfor %}
</tr>
{% for row in notice_settings.rows %}
<tr>
<td>{% trans row.notice_type.display %}<br/>
<span class="notice_type_description">{% trans row.notice_type.description %}</span>
</td>
{% for cell in row.cells %}
<td>
<input type="checkbox" name="{{ cell.0 }}" {% if cell.1 %}checked="yes"{% endif %}/>
</td>
{% endfor %}
</tr>
{% endfor %}
<tr>
<td><input type="submit" value="{% trans "Change" %}" /></td>
</tr>
</table>
</form>
The view you show only manages the processing of the POSTed notification but not the displaying of a form in a page. You can create your own form that includes a field called form_label and include it in whatever page that posts to this view (could be a hidden input).

Categories