I have created a table in DB Browser SQLite with real data input. How do I link the SQLite with flask so that the table will be displayed in the html. I want the html part to be displayed exactly the same as DB Browser Sqlite.
This is my app.py
#app.route('/viewrec', methods=['POST', 'GET'])
def viewrec():
try:
if request.method == 'POST':
use = session['user'].get("name")
ema = session['user'].get("preferred_username")
depart = request.form['depart']
type = request.form['type']
uploadre = request.form['uploadre']
amt = request.form['amt']
description = request.form['description']
if request.form.get("price"):
price_checked = "Yes"
else:
price_checked = "No"
conn = sql.connect(db_path)
c = conn.cursor()
c.execute('SELECT * FROM SubmitClaim')
rows = c.fetchall()
return render_template("viewpastclaim.html", rows=rows)
except:
# for row in rows:
# print(row)
#
# conn.close()
return render_template('viewpastclaim.html')
This is my viewpastclaim.html
I tried to call the various variables from App.py and use them with rows['Name']
<form action="/viewrec" METHOD="POST" >
<!-- Generate all the claim content -->
<table style=" font-family: arial, sans-serif;
width: 60%;
border: 1px solid black;
margin-left:500px;
margin-top: 100px;
text-align: center;
padding:20px;">
<tr>
<th class="type">Name</th>
<th>Email</th>
<th>Department</th>
<th>ClaimType</th>
<th>UploadReceipt</th>
<th>ClaimAmount</th>
<th>checkbox</th>
<th>ClaimDescription</th>
</tr>
{% for rows in SubmitClaim %}
<tr>
<td>rows['Name']</td>
<td>rows['Email']</td>
<td>rows['Deparment']</td>
<td>rows['ClaimType']</td>
<td>rows['UploadReceipt']</td>
<td>rows['ClaimAmount']</td>
<td>rows['checkbox']</td>
<td>rows['ClaimDescription']</td>
</tr>
{% endfor %}
</table>
<!-- View all the claims -->
<button type="submit", class="viewall-button" name="save", value="save">View All</button>
</form>
If you are able to solve them, please drop a msg below. Thank you for your time.
You have to wrap your Python variables in {{ }} to show them in HTML format. You also have some errors in your code. You have to replace 'SubmitClaim' with rows since you passed that in your python function. So the correct code would be:
{% for row in rows %}
<tr>
{% for data in row %}
<td>{{ data }}</td>
{% endfor %}
</tr>
{% endfor %}
I think something like that should work. You are giving the info to the template inside of "rows" not inside of "SubmitClaim"
<tr>
<th class="type">Name</th>
<th>Email</th>
<th>Department</th>
<th>ClaimType</th>
<th>UploadReceipt</th>
<th>ClaimAmount</th>
<th>checkbox</th>
<th>ClaimDescription</th>
</tr>
{% for row in rows %}
<tr>
<td>row['Name']</td>
<td>row['Email']</td>
<td>row['Deparment']</td>
<td>row['ClaimType']</td>
<td>row['UploadReceipt']</td>
<td>row['ClaimAmount']</td>
<td>row['checkbox']</td>
<td>row['ClaimDescription']</td>
</tr>
{% endfor %}
If you still can't get it to work I suggest you use SQL-Alchemy to manage the database. That should make everything easier.
Related
I'm trying to render results of a group by query from a view to an HTML table but it is returning nothing. I originally had success in listing all results, but after applying the sum aggregation I can't get it to appear.
Django View - with Group By
def get_asset_price(request):
# CryptoAssets is the model
obj = CryptoAssets.objects.filter(user_id=request.user.id).values('symbol')
obj = obj.annotate(total_units=Sum('units'),
total_cost=Sum('cost'))\
.order_by('symbol')
# Returns list of dictionaries
context = {
'object': obj
}
return render(request, 'coinprices/my-dashboard.html', context)
HTML
<style>
table, th, td {
border: 1px solid black;
}
</style>
<div class="container">
<h1>My Dashboard</h1>
<table>
<tr>
<th>Symbol</th>
<th>Total Units</th>
<th>Total Cost</th>
</tr>
{% for row in object %}
<tr>
<td>{{ row.symbol }}</td>
<td>{{ row.units }}</td>
<td>{{ row.cost }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
I'll provide the view below that worked without the group by.
Django View - No group by
def get_asset_price(request):
# CryptoAssets is the model
obj = CryptoAssets.objects.all().filter(user_id=request.user.id)
# Returns list of objects
context = {
'object': obj
}
return render(request, 'coinprices/my-dashboard.html', context)
I think you're calling an attribute which does not exist on your object. The type of your object is a list of dictionaries. Change your template codes to something like this (this is the simplest way and maybe you can improve it later like adding a template tag similar to the one that is used in this question):
<table>
<tr>
<th>Symbol</th>
<th>Total Units</th>
<th>Total Cost</th>
</tr>
{% for row in object %}
<tr>
{% for key, value in row.items %}
<td>{{ key }}</td>
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
I have a flask route rendering a template (method1_result.html) containing a dataframe table. Clicking the table row will send the cell value to another flask route to render a new template (method2_result.html). This last operation is showing a new result relevant to the Cell Clicked but the new html page (method1_result.html) is displaying the result twice.
main.py
#app.route("/method1",methods=['POST', 'GET'])
def method1():
'
'
return render_template('method1_result.html')
#app.route("/method2",methods=['POST', 'GET'])
def method2():
if request.method == 'POST':
# get info here to render page!
.
.
return render_template('method2_result.html',var1=var1)
method1.html
{% block content %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<br/>
<h3 align="center" style="color:blue" style="font-family:verdana">Method1 Result</h3>
<br/>
<div class="container-fluid">
<table id="table" class="table table-striped table-bordered" style="width: 100%">
<thread>
<tr>
{% for header in table[0].keys() %}
<th>{{header}}</th>
{% endfor %}
</tr>
</thread>
<tbody>
{% for row in table %}
<tr class='clickable-row'>
<td>{{row['Field1']}}</td>
<td>{{row['Field2']}}</td>
<td>{{row['Field3']}}</td>
<td>{{row['Field4']}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script>
highlight_row();
function highlight_row(var1='') {
var table = document.getElementById('table');
var cells = table.getElementsByTagName('td');
for (var i = 0; i < cells.length; i++) {
// Take each cell
var cell = cells[i];
// do something on onclick event for cell
cell.onclick = function () {
// Get the row id where the cell exists
var rowId = this.parentNode.rowIndex;
var rowsNotSelected = table.getElementsByTagName('tr');
for (var row = 0; row < rowsNotSelected.length; row++) {
rowsNotSelected[row].style.backgroundColor = "";
rowsNotSelected[row].classList.remove('selected');
}
var rowSelected = table.getElementsByTagName('tr')[rowId];
rowSelected.style.backgroundColor = "yellow";
rowSelected.className += " selected";
msg = 'The Failure Message : ' + rowSelected.cells[6].innerHTML;
var var1 = rowSelected.cells[3].innerHTML;
$.ajax({
url:"/method2",
method:"POST",
data:{var1:var1},
success:function(data)
{
$('tbody').html(data);
$('tbody').append(data.htmlresponse);
},
})
}
}
}
</script>
{% endblock %}
method2.html
{% block content %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<br/>
<h4 align="center" style="color:blue" style="font-family:verdana">Method2 result</h4><br/>
<br/>
<table id="table" class="table table-striped table-bordered table-hover" style="width: 100%">
<thread>
<tr>
{% for header in table1[0].keys() %}
<th>{{header}}</th>
{% endfor %}
</tr>
</thread>
<tbody>
{% for row in table1 %}
<tr>
<td>{{row['Start']}}</td>
<td>{{row['OperationID']}}</td>
<td style="color:red">{{row['Failure Message1']}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
Not sure what Am doing wrong ?
In your code, you are doing an asynchronous call (ajax). An asynchronous call does not reload a page. This means that user is still on method1_result.html when the result (i.e. method2_result.html) comes in.
Your code also says to simply append the entire method2_result.html to method1_result.html page. In fact, you do it twice because you have
// First you append the entire response i.e. the entire method2 result
$('tbody').html(data);
// Then you try to do it a second time but just the 'htmlresponse' (not sure where you are getting this fro
$('tbody').append(data.htmlresponse);
If you want to replace the entire page (method1_result) with the entire contents of method2_result, then you don't need an Ajax call. Replace that ajax call with code that creates a form, creates an input element with the values of the data that you want to pass to the server, and then submits the form. Since this is not an ajax call, it will load a new page which is method2.html
var form = document.createElement("form");
form.method = "POST";
form.action = "/method2";
var elem = document.createElement("input");
elem.name= var1;
elem.value= var1;
form.appendChild(elem1);
document.body.appendChild(form);
form.submit();
If you don't want to replace the entire page (maybe you want to replace the body of the existing page with the new page), then you can't just do append which means to add to the existing content, unless you have first cleared the existing content. You have 2 options
Option 1
$('tbody').empty() // Remove the current contents
$('tbody').append(data); // Add the new contents
Option 2
$('tbody').html(data)
I am trying to make a path lab database system, Where I have models as follows:
Client model: to store client name
CBC test model: child to client model.
Liver test model: child to client model.
kidney function test model: child to client model.
my purpose is that if we enter client id and date to form it goes to result page and shows all the test performed to that particular client on that date.
I made a client model and models for each tests.
from django.shortcuts import render
from .models import client, cbc, lft, kft
from django.db.models import Q
def index(request):
return render(request, 'vmr/index.html')
def result(request):
client = request.POST['client']
date = request.POST['date']
r = cbc.objects.filter(Q(id = client ) & Q(Date__iexact = date))
l = lft.objects.filter(Q(id = client ) & Q(Date__iexact = date))
k = kft.objects.filter(Q(id = client ) & Q(Date__iexact = date))
context = { "results": r, "liver": l, "kidney":k}
return render(request, 'vmr/result.html', context=context )
My Result template for results is:
{% if results %}
{% for result in results%}
<h3 style="padding-left: 10%;"> DATE:{{result.Date}} </h3>
<table style="width:70%">
<tr>
<th>PARAMETER</th>
<th>UNIT</th>
<th>VALUE</th>
<th>RANGE</th>
<th>INFERENCE</th>
</tr>
<tr>
<td> RBC </td>
<td> million/mm3 </td>
<td> {{result.RBC}} </td>
<td> 5.5-8.5 </td>
<td> {% if result.RBC < 12 %}
ANEMIA
{% else %}
NORMAL
{% endif %} </td>
</tr>
<tr>
<td> HEMOGLOBIN </td>
<td> g/dl </td>
<td> {{result.Hemoglobin}} </td>
<td> 12-18 </td>
<td> {% if result.Hemoglobin < 12 %}
ANEMIA
{% else %}
NORMAL
{% endif %} </td>
</tr>
</table>
{% endfor %}
{% endif %}
<h3>LIVER TEST</h3>
{% if livers %}
{% for liver in livers%}
<h3 style="padding-left: 10%;"> DATE:{{liver.Date}} </h3>
<table style="width:70%">
<tr>
<th>PARAMETER</th>
<th>UNIT</th>
<th>VALUE</th>
<th>RANGE</th>
<th>INFERENCE</th>
</tr>
<tr>
<td> SGOT </td>
<td> million/mm3 </td>
<td> {{liver.SGOT}} </td>
<td> 9-49 </td>
<td> {% if liver.SGOT < 9 %}
ABNORMAL VALUE
{% elif liver.SGOT > 49 %}
HEPATOMEGALY
{% else %}
NORMAL
{% endif %}
</td>
</tr>
{% endfor %}
{% endif %}
</table>
my form index template is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="{% url 'result'%}" enctype="application/x-www-form-urlencoded" method="POST" >
{% csrf_token %}
<input type="text" name="client">
<label for="client">CLIENT ID</label>
<input type="date" name = "date">
<label for="date">DATE</label>
<button type="submit" name = "submit">SUBMIT</button>
</form>
</body>
</html>
Everything is fine for cbc results but when I include tags for liver and kidney it shows error.
What is the correct approach to get all tests for a client on particular date on one template?
One approach I think can be if I create a Tests Records Model which is child of client, cbc, lft, kft so that we query Records model by date and client id and get everything on page.
Please can anyone suggest best method to get all test done to a particular client on particular date on one page.
Careful: request.POST contains strings, so date will NOT yet be a datetime.date object.
You might want to add explicit date parsing, maybe something like this:
try:
date = datetime.datetime\
.strptime(request.POST.get('date', ''), '%d-%m-%Y')\
.date()
except ValueError:
date = None
And maybe you want to transform request.POST['client'] from string to integer as well (I assume that ID is integer, because that is the standard Django ID field). Or maybe you even want to query the client model to ensure that the given client ID exists:
try:
client_obj = client.objects.get(pk=request.POST.get('client', ''))
client_id = client_obj.pk
except (ValueError, client.DoesNotExist):
client_id = None
And your queries can be simplified, because the Q() is not necessary for simple queries; also the __exact filter is not necessary in this part, because it is the default filter.
And last: you don't show your models, but I assume that the results, liver and kidney models each have a ForeingKey to client, so you should filter by client_id, not on id directly.
So your final view could look something like this:
def result(request):
try:
client_obj = client.objects.get(pk=request.POST.get('client', ''))
client_id = client_obj.pk
except (ValueError, client.DoesNotExist):
client_id = None
try:
date = datetime.datetime\
.strptime(request.POST.get('date', ''), '%d-%m-%Y')\
.date()
except ValueError:
date = None
context = {
"results": cbc.objects.filter(client_id=client_id, Date=date),
"liver": lft.objects.filter(client_id=client_id, Date=date),
"kidney": kft.objects.filter(client_id=client_id, Date=date),
}
return render(request, 'vmr/result.html', context=context)
I have SQLite database which contains data regarding products such as Product Name, Description and Like which shows if the user likes or doesn't like the product.
A user search for different products which populate a table with the name, description and a checkbox which is clicked in if the value of Like is 1 in the database and unchecked if not.
I have implemented the button through (as seen in index.html)
<form method = "POST"> <input type="checkbox" name="like" {% if product.like == 1 %} checked {% else %} {% endif %}>
I now want the user to be able to check and uncheck the boxes in the table, and then press a button that updates the Like column in the database, how do I do this?
(I can't even access the value of the button in app.py. When trying print(requests.form['like']) on the line after name=requests.form['search'] it returns BadRequestKeyError: The browser sent a request that this server could not understand. KeyError: 'like')
app.py
...
product = []
#app.route('/', methods = ['POST'])
def index():
name = None
if request.method == 'POST':
name = request.form['search']
if name is not None or name != "":
query_product = Products.query.filter(Products.productname==name).first()
if (query_product is not None) and (query_product not in product):
company.append(query_company)
print(company, file = sys.stderr)
return render_template('index.html', companies = company)
Products class
class Products(db.Model):
index = db.Column(db.Integer(), primary_key = True)
productname = db.Column(db.String(), primary_key = False)
description = db.Column(db.String(), primary_key = False)
like = db.Column(db.Integer(), primary_key = False)
...more columns
index.html
<!-- /templates/index.html -->
{% extends 'base.html' %}
{% block content %}
<form method="POST">
<input type="text" placeholder="Search for Product.." name="search">
<button type="submit" name="submit">Search</button> <button type="submit" name="update" value = company.index style = margin-left:45%>Update</button>
<div class="product-container" style="overflow: auto; max-height: 80vh">
<div class="table-responsive">
<table class="table" id="products">
<thead>
<tr>
<th scope="col">Product Name</th>
<th scope="col">Description</th>
<th scope="col">Like</th>
</tr>
</thead>
<tbody>
{% for product in products %}
<tr {{company.index}}>
<th scope="row">{{ product.productname}}</th>
<td> {{ product.description }} </td>
<td><form method = "POST"> <input type="checkbox" name="like" {% if product.like == 1 %} checked {% else %} {% endif %}></form></td>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
I guess you need to do this with javascript and add another route to your backend which then updates the database.
maybe something like this, if it should happen automatically:
<input type="checkbox" onchange="updateLike('productId', this.checked)">
<script>
async function updateLike(productId, doesLike) {
let response = await fetch("http://localhost/products/productId/like", {
method:"POST",
headers: {"Content-Type":"application/json"},
body: JSON.stringify({
productId: productId,
like: doesLike
})
});
}
</script>
or you could add a button which sends the request to the server.
<input type="checkbox" name="like"/>
<button onclick="updateLike('productId', document.querySelector('input[name=like]').checked)">confirm</button>
I use Pandas to get and transform some data from database and now I'd like to print the score dynamic, that is without page refresh. I've already tried: {{ mydata|safe}} and I get the whole information but everything is together not in table.
I use Pandas to create HTML table from dataframe mydata.to_html()) and I get something like that:
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>Part_number</th>
<th>Type_name</th>
<th>Short_desc</th>
<th>Price_1</th>
<th>Price_2</th>
<th>VAT</th>
<th>DB_source</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>565_MLNN7_101</td>
<td>AIR_FILTER</td>
<td>AIR_FILTER_GREEN</td>
<td>1.20</td>
<td>6.30</td>
<td>23%</td>
<td>Murexin</td>
</tr>
<tr>
<th>1</th>
<td>217_NE307_115</td>
<td>CABLE</td>
<td>CABLE_POWER_AC</td>
<td>0.84</td>
<td>3.20</td>
<td>23%</td>
<td>DB_1</td>
</tr>
</tr>
</tbody>
</table>
Do You know how print the table using Jinja2 ?
The jinja template that you need is something like this:
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>Part_number</th>
<th>Type_name</th>
<th>Short_desc</th>
<th>Price_1</th>
<th>Price_2</th>
<th>VAT</th>
<th>DB_source</th>
</tr>
</thead>
<tbody>
{% for row in mydata %}
<tr>
<th>{{loop.index0}}</th>
<td>{{row['Part_number']}}</td>
<td>{{row['Type_name']}}</td>
<td>{{row['Short_desc']}}</td>
<td>{{row['Price_1']}}</td>
<td>{{row['Price_2']}}</td>
<td>{{row['VAT']}}</td>
<td>{{row['DB_source']}}</td>
</tr>
{% endfor %}
</tbody>
</table>
Check jinja2 documentation for more details
Sure
Here is my code for html template:
{% extends "header.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block content %}
<div class="container">
<form class="form-signin" method="POST" action="/search">
<div class="panel panel-default">
<div class="panel-heading">Service Part Inquiry</div>
<div class="panel-body">
{{ form.hidden_tag() }}
{{wtf.form_field(form.FGPN_Search)}}
{{wtf.form_field(form.AssyTypeName_Search)}}
{{wtf.form_field(form.Source_Search)}}
<button type="submit" class="btn btn-primary btn-xsy">Search</button>
</div>
</div>
</form>
</div> <!-- /container -->
{{data|safe}}
{% endblock %}
Code for function below. Actually I check condition only for "Source_Search": "Murexin", that why I deleted some codes (will be easier to understand for You :) I respect Your time):
#app.route('/search',methods=['GET', 'POST'])
def search():
form = SearchForm()
if request.method == 'POST':
FGPN_Search = form.FGPN_Search.data
AssyTypeName_Search = form.AssyTypeName_Search.data
Source_Search = form.Source_Search.data
(...)
elif Source_Search == 'Murexin':
if len(FGPN_Search)>1:
tablePLM=read_sql_query(select1 + "\'" + FGPN_Search + "\'" + select2 + "\'" + AssyTypeName_Search + "\'",CurDB_2)
tableSIC = read_sql_query(selectSIC + "\'" + FGPN_Search + "\'",CurDB_1)
mydata = pd.merge(tablePLM, tableSIC, on='PM_PARTNUMBER',how='outer')
mydata.to_html()
return render_template('search.html', form=form,data=mydata)
elif Source_Search == 'test':
return "<h1>test</h1>"
else:
flash("Please write anything.")
return render_template('search.html',form=form)
return render_template('search.html', form=form)