Rendering multiple pandas html tables side-by-side - python

I have produced individual html tables showing work orders from multiple departments , and a running count rendered in the header of how many are orders are 'Completed' out of the 'Total' number of orders in that department. This all works fine, but I cannot find a way, clever or otherwise, to render these tables side by side on an html page. I can't have the tables on top of one another because the page will be appear static on a large monitor through a raspberry pi, so scrolling isn't an option.
pd.set_option('colheader_justify', 'center') # FOR TABLE <th>
table1 = CNC.to_html(classes='mystyle', na_rep='', index = False)
status1 = f"{C10} of {Total10} Completed"
html_string = f'''
<html>
<head><title>HTML Pandas Dataframe with CSS</title></head>
<link rel="stylesheet" type="text/css" href="df_style.css"/>
<body>
<h1 style="border:2px solid DodgerBlue;font-size:35px;text-align:center"> C N C </h1>
<h1 style="background-color:MediumSeaGreen;font-family:verdana;font-size:40px;text-align:center"> {status1} </h1>
{table1}
<script>setInterval(() => location.reload(), 60000);</script>
</body>
</html>.
'''
with open("CNC.html", mode = 'w') as f:
f.write(html_string.format(table=CNC.to_html(classes='mystyle', na_rep='', index = False)))
CSS
.mystyle {
font-size: 15pt;
font-family: Arial;
border-collapse: collapse;
border: 1px solid silver;
}
.mystyle td, th {
padding: 10px;
}
.mystyle tr:nth-child(even) {
background: #E0E0E0;
}
.mystyle tr:hover {
background: silver;
cursor: pointer;
}
.mystyle {
margin: auto;
padding: 0;
}
.mystyle {
text-align: center;
width: 100%;
}
Rendered CNC html table
This obviously creates and renders only a single table on an html page
It would be great if there was some CSS magic I could use so that I could just apply that stylesheet to each department's html.

Related

Importing SVG into HTML

I'm very new to HTML...just started yesterday. The problem I'm having is that when I'm importing an SVG into my HTML script, the text gets all gargled. For example, Peak Metagene Plot becomes 2eak MetaCene 2lot. It's almost like certain letters are changed.
I have made a python script to read in an SVG file like such (I'm calling in two SVGs here, violin and metagene_reads):
# violin
if args['--violin']:
violin_file = open(args['--violin'], 'r')
violin_txt = violin_file.read()
violin_hide = ''
else:
violin_txt = ''
violin_hide = 'hidden'
# metagene reads
if args['--metagene_reads']:
metagene_reads_file = open(args['--metagene_reads'], 'r')
metagene_reads_txt = metagene_reads_file.read()
metagene_reads_hide = ''
else:
metagene_reads_txt = ''
metagene_reads_hide = 'hidden'
I then use this code to feed into an HTML template. Without pasting the entire code, I'll only list the contents that are giving me the weird text:
Specify font type...
<!DOCTYPE html>
<html>
<h1><link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.18/css/jquery.dataTables.css">
<style>
td {
text-align: center;
vertical-align: middle;
}
h1 {
font-size: 36px;
font-weight: bold;
font-family: Georgia, Times, "Times New Roman", serif;
}
h2 {
font-size: 24px;
font-family: Georgia, Times, "Times New Roman", serif;
}
h3 {
margin-bottom: 0px;
padding: 0px;
margin-left: 300px;
font-size: 24px;
font-family: Georgia, Times, "Times New Roman", serif;
}
.initiallyHidden { display: none; }
.toggle {
background-color: #4CAF50;
border: none;
color: white;
padding: 8px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 12px;
margin-bottom: 20px;
}
....other contents like tables, etc.
Below is where I'm importing the SVGs called in from the python script (code shown above). This is where I'm getting the weird formatting issues.
<br>
{{metagene_reads_txt}}
<br>
<h2 {{metagene_peaks_hide}}><center>MultipleMetagene Peaks Plot</center></h2>
<p {{metagene_peaks_hide}}>
<br>
<button class="toggle" onclick="metagenePeaks()">Click to learn more</button>
<div id="metagenePeaksID" class="initiallyHidden">
The multiple metagene peaks plot illustrates the average peak coverage of 5' UTR, CDS, and 3' UTR features.
</div>
<script>
function metagenePeaks() {
var x = document.getElementById("metagenePeaksID");
display = x.style.display;
x.style.display = (display && display !== 'none') ? 'none' : 'block';
}
</script>
<br>
{{metagene_peaks_txt}}
<br>
<h2 {{violin_hide}}><center>Gene Count Violin Plot</center></h2>
<p {{violin_hide}}>
<br>
<button class="toggle" onclick="violinFunction()">Click to learn more</button>
<div id="violinDIV" class="initiallyHidden">
The violin plot illustrates the distribution of gene counts for each sample. The gene counts were normalized for differences in library depth and log transformed.
</div>
<script>
function violinFunction() {
var x = document.getElementById("violinDIV");
display = x.style.display;
x.style.display = (display && display !== 'none') ? 'none' : 'block';
}
</script>
<br>
{{violin_txt}}
<br>
</p>
</body>
</html>
Any help would be greatly appreciated.
What you are doing right now is taking SVG content, something like this:
<svg version="1.1"
baseProfile="full"
width="300" height="200"
xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="black" />
<circle cx="150" cy="100" r="90" fill="blue" />
</svg>
And just copy+pasting that into the HTML, which the browser does not understand.
Instead, you should be linking to the SVG file using something like this (although depending on how this is hosted the relative path may need to be adjusted):
<img src="{{violin_file}}">
If you really want to embed it within the code (which I generally do not recommend), you can Base64 Encode it and embed that, something like this:
import base64
with open(violin_file, "rb") as image_file:
violin_base64 = str(base64.b64encode(image_file.read()),'utf-8')
And then instead of {{violin_txt}} you would do:
<img src="data:image/svg+xml;base64,{{violin_base64}}" />

xhtml2pdf how manage the class attribute?

In my django project i have to create a pdf file from my html.
For this purpose i use xhtml2pdf and in my html section i write:
<style type="text/css">
body {margin:0;padding:0;background-color:#FAFAFA;font:8pt "Tahoma";}
* {box-sizing:border-box;-moz-box-sizing:border-box;}
th, td {border:1px solid black;border-collapse:collapse;}
#page {
size: a4 portrait;
margin: 1cm auto;
padding: 1cm;
margin: 1cm auto;
border: 1px #D3D3D3 solid;
border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
table {
-pdf-keep-in-frame-mode: shrink;
border:1px solid black;
border-collapse:collapse;
}
p {margin:0;padding:0;line-height:1.4em}
.column-50-left {width:49.5%;display:inline-block;vertical-align:top;padding-right:15px}
.column-50-right {width:49.5%;display:inline-block;vertical-align:top;padding-left:15px}
.invoice {font-size:6pt}
.invoice td {height:50px;vertical-align:top;padding:5px;}
.destinatario td {height:120px;vertical-align:top;padding:5px;font-size:6pt}
.description th {height: 30px}
.description td {height: 50px}
.top-10 {margin-top:10px}
.top-15 {margin-top:15px}
.top-20 {margin-top:20px}
.padding-top-4 {padding-top:4px}
.padding-bottom-15 {padding-bottom:15px}
.padding-bottom-30 {padding-bottom:30px}
.border-top {border-top:1px solid #000000}
</style>
but when i use my attributes on elements for apply the styles nothing appen for example:
<table style="width:80%" class="invoice top-10">
or
<div class="border-top top-10 invoice padding-top-4 padding-bottom-15"><p>PORTO / <em>Freight</em></p></div>
How can i apply my class style to my pdf output in xhtml2pdf?
So many thanks in advance

How to apply CSS class (my style) to Pandas DataFrame using to_html

Sorry, I am new to HTML and CSS.
The goal is to create HTML table from dataframe and send it via email.
But how can I stylish the output table?
Let's I want different background header, font, etc?
This is the style I want to implement:
mystyle =
'''
.mystyle {
font-size: 11pt;
font-family: Arial;
border-collapse: collapse;
border: 1px solid silver;
}
.mystyle td, th {
padding: 5px;
}
.mystyle tr:nth-child(even) {
background: #E0E0E0;
}
.mystyle tr:hover {
background: silver;
cursor: pointer;
}
'''
So how can I implement mystyle into below code and get stylish table? I tried df.to_html(classes=mystyle) but it did not work
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import pandas as pd
import datetime as dt
yesterday = dt.datetime.now() - dt.timedelta(days=1)
date = "'" + yesterday.strftime('%m-%d-%Y') + "'"
df = pd.DataFrame({
'Position': ['DBA','CEO','Underwriter']
,'Salary': [100000,300000,60000]
,'Posted':['2019-01-01', '2019-05-01', '2019-03-15']
,'Link': ['myjob.com','ceo.com','insurance.com']
})
html = """\
<html>
<head>Report for """ + date + """</head>
<body>
{0}
</body>
</html>
""".format(df.to_html())
print(html)
You don't need to create a css file for this. Everything can work just fine if you concat them to a string. Here is how I normally do it:
message_start = f"""
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Report for {date}</title>"""
message_style = """
<style type="text/css" media="screen">
#customers {
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
font-size: 12px;
border-collapse: collapse;
width: 100%;
}
#customers td, #customers th {
border: 1px solid #ddd;
padding: 8px;
}
#customers tr:nth-child(even){background-color: #f2f2f2;}
#customers tr:hover {background-color: #ddd;}
#customers th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #4CAF50;
color: white;
}
</style>
</head>
<body>
"""
message_body = df.to_html(index=False, table_id="customers") #set table_id to your css style name
message_end = """</body>"""
messages = (message_start + message_style + message_body + message_end)
part = MIMEText(messages, 'html') # create MIMEText
msg.attach(part)
...

How to remove margins from PDF? (Generated using WeasyPrint)

I am trying to render a PDF document within my Flask application. For this, I am using the following HTML template:
<!DOCTYPE html>
<html>
<head>
<style>
#page {
margin:0
}
h1 {
color:white;
}
.header{
background: #0a0045;
height: 250px;
}
.center {
position: relative;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align:center;
}
</style>
</head>
<body>
<div class="header">
<div class="center">
<h1>Name</h1>
</div>
</div>
</body>
</html>
I keep getting white margins at the top and right/left of my header section:
Is there a way to remove them?
Edit:
Below is the code used to generate the PDF file using WeasyPrint in my Flask app:
def generate_pdf(id):
element = Element.query.filter_by(id=id).first()
attri_dict = get_element_attri_dict_for_tpl(element)
html = render_template('element.html', attri_dict=attri_dict)
pdf = HTML(string=html).write_pdf()
destin_loc = app.config['ELEMENTS_FOLDER']
timestamp = dt.datetime.now().strftime('%Y%m%d%H%M%S')
file_name = '_'.join(['new_element', timestamp])
path_to_new_file = destin_loc + '/%s.pdf' % file_name
f = open(path_to_new_file, 'wb')
f.write(pdf)
filename = return_latest_element_path()
return send_from_directory(directory=app.config['ELEMENTS_FOLDER'],
filename=filename,
as_attachment=True)
Maybe you forgot " ; " or/and " mm ",
it works:
#page {
size: A4; /* Change from the default size of A4 */
margin: 0mm; /* Set margin on each page */
}
The weasyprint uses 3 sources of css, one of them is default user agent stylesheet
(https://doc.courtbouillon.org/weasyprint/stable/api_reference.html#supported-features)
That defines:
body {
display: block;
margin: 8px;
}
make sure to override that margin on tag and you will loose the margin.

Tree display of a scope database with jinja and flask

Disclaimer: Title may not be the best way to describe what I am about to ask. If you have a better title in mind, please put it instead of mine
I am working on a scope database which will allow me to know what user has access to what ressource. To put it simply:
admin
super-foo
manager-foo-1
user-1
user-2
manager-foo-2
user-3
user-4
super-bar
manager-bar-1
user-5
user-6
manager-bar-2
user-7
user-8
admin has access to all users underneath him.
super-foo has access to all users underneath him, but not the ones of super-bar
etc... until your reach for example user-1, which doesn't have access to anything except himself
(when I say underneath, I mean hierarchically)
(when I say acces, I mean access data, the users, whatever)
Each entry of my DB is like this (using manager-foo-1 for example):
id=manager-foo-1 (I have a function that I can call to get everything on the user as the uuid is the hash key of my user DB (because i'm using their usernames here, but the ids are uuids.))
parents_id=['super-foo']
children_id=['user-1', 'user2']
Here's my DB right now (I've replaced the uuid4 with names):
for user_scope in UserScope.scan():
print("User {} has parents {} and childs {}".format(user_scope.id, user_scope.parents_id, user_scope.children_id))
User manager-foo has parents [super-foo] and childs [user-1, user-2]
User admin has parents None and childs [super-foo]
User super-foo has parents [admin] and childs [manager-foo]
User user-1 has parents [manager-foo] and childs None
User user-1 has parents [manager-foo] and childs None
childs are set to None when you reach the bottom, but that shouldn't really matter
What I would like it to get a pretty display, or at least an understandable display or that DB, when given an id. So if given admin, display EVERYTHING. If given user-1, only display user-1 etc...
I've used a little bit of jinja templates but nothing advanced, the furthest I've got was this for loop to make a user list (using a macro)
{% for user in user_list %}
{% from "user_line.html" import user_line %}
{{user_line(user)}}
{% endfor %}
I'm having trouble to wrap my head around how to do this, what should the layout be, in what order should I display them and should I use macros? templates?
Thanks in advance
I ended up finding a way to solve this.
First of all, I generated a dictionnary containing everything I need scopewise:
def get_all_children_tree(uid):
scope = get_userscope_dict(user.client_id)
children = []
if scope['children_id'] is None:
ret = {
"user": scope['id'],
"children": None
}
return ret
for child_id in scope['children_id']:
children.append(get_all_children_tree(child_id))
ret = {
"user": scope['id'],
"children": children
}
return ret
This will give me something like this:
{
'user':'cbf7f365-db8a-419b-9f8c-c24b2ce01361',
'children':[
{
'user':'17bc0bdc-892b-4e47-b749-36c1687c0992',
'children':[
{
'user':'d51056b7-60fe-437f-abe0-4a30076df4cd',
'children':[
{
'user':'14f1963b-0f64-4431-a52f-819877d6096c',
'children':None
},
{
'user':'40765a8d-6001-4146-9d1f-ce3fd95646c7',
'children':None
}
]
},
{
'user':'8a617821-e189-4b17-ac67-597ca79b98e9',
'children':[
{
'user':'42af51b0-2810-4004-b063-a4789631bb2e',
'children':None
},
{
'user':'26d43e72-4e45-40c3-ab2b-98c637dde5aa',
'children':None
}
]
}
]
}
]
}
Then I wrote a jinja template like so :
{% extends "main.html" %}
{% block body %}
<!-- tree -->
<style type="text/css">
ul.tree {
overflow-x: auto;
white-space: nowrap;
}
ul.tree,
ul.tree ul {
width: auto;
margin: 0;
padding: 0;
list-style-type: none;
}
ul.tree li {
display: block;
width: auto;
float: left;
vertical-align: top;
padding: 0;
margin: 0;
}
ul.tree ul li {
background-image: url(data:image/gif;base64,R0lGODdhAQABAIABAAAAAP///ywAAAAAAQABAAACAkQBADs=);
background-repeat: repeat-x;
background-position: left top;
}
ul.tree li span {
display: block;
width: 5em;
/*
uncomment to fix levels
height: 1.5em;
*/
margin: 0 auto;
text-align: center;
white-space: normal;
letter-spacing: normal;
}
</style>
<!--[if IE gt 8]> IE 9+ and not IE -->
<style type="text/css">
ul.tree ul li:last-child {
background-repeat: no-repeat;
background-size:50% 1px;
background-position: left top;
}
ul.tree ul li:first-child {
background-repeat: no-repeat;
background-size: 50% 1px;
background-position: right top;
}
ul.tree ul li:first-child:last-child {
background: none;
}
ul.tree ul li span {
background: url(data:image/gif;base64,R0lGODdhAQABAIABAAAAAP///ywAAAAAAQABAAACAkQBADs=) no-repeat 50% top;
background-size: 1px 0.8em;
padding-top: 1.2em;
}
ul.tree ul {
background: url(data:image/gif;base64,R0lGODdhAQABAIABAAAAAP///ywAAAAAAQABAAACAkQBADs=) no-repeat 50% top;
background-size: 1px 0.8em;
margin-top: 0.2ex;
padding-top: 0.8em;
}
</style>
<!-- <[endif]-->
<!--[if lte IE 8]>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript">
/* Just to simplify HTML for the moment.
* This could easily be replaced by inline classes.
*/
$(function() {
$('li:first-child').addClass('first');
$('li:last-child').addClass('last');
$('li:first-child:last-child').addClass('lone');
});
</script>
<style type="text/css">
ul.tree ul li {
background-image: url(pixel.gif);
}
ul.tree ul li.first {
background-image: url(left.gif);
background-position: center top;
}
ul.tree ul li.last {
background-image: url(right.gif);
background-position: center top;
}
ul.tree ul li.lone {
background: none;
}
ul.tree ul li span {
background: url(child.gif) no-repeat 50% top;
padding-top: 14px;
}
ul.tree ul {
background: url(child.gif) no-repeat 50% top;
margin-top: 0.2ex;
padding-top: 11px;
}
</style>
<[endif]-->
<!-- page presentation -->
<style type="text/css">
body {
font-family:sans-serif;
color: #666;
text-align: center;
}
A, A:visited, A:active {
color: #c00;
text-decoration: none;
}
A:hover {
text-decoration: underline;
}
ul.tree,
#wrapper {
width: 960px;
margin: 0 auto;
}
ul.tree {
width: 650px;
}
p {
margin-top: 2em;
}
</style>
<div id="page-wrapper">
<p> {{ data }}</p>
<div id="wrapper">
<ul class="tree">
<li>
<span> {{ get_user(data['user']).username }}</span>
<ul>
{%- for child in data['children'] recursive %}
<li>
<span> {{ get_user(child['user']).username }} </span>
{%- if child['children'] -%}
<ul>
{{ loop(child['children']) }}
</ul>
{%- endif %}
</li>
{%- endfor %}
</ul>
</li>
</ul>
</div>
</div>
{% endblock %}
Here's the final result

Categories

Resources