使用python的条件格式html表行 [英] Conditional format html table rows with python
问题描述
我必须有条件地格式化用Python生成的html表的行.我以前不得不对表列进行排序,并使用javascript进行了排序.而不是有条件地格式化html行上的background-color,我如何修改Python代码来做到这一点? 结果"行是成功",然后行是绿色,哪里行是失败",然后行是红色?该代码段显示了我是如何尝试仅使用js做到这一点的.代码是2个py文件,js代码位于代码 function resultFormating 的末尾.
I must conditionally format rows of an html table that is generated with Python. I previously had to sort table columns and did so using javascript. Rather than conditionally format background-color on html rows how can I modify Python code to do this? where 'results' row is 'success' then row is green, where row is 'fail' then row is red? the code snippet shows how I tried to do this with js only. Code is 2 py files, the js code is at end of code function resultFormating.
import os
import sys
import random
#
# update PYTHONPATH
#
sys.path.append(os.getcwd())
from test_output import Test_Output, Test_record
desc_choices = ('Cat', 'Dog', 'Pig', 'Horse', 'Mule')
info_choices = ('Red', 'Blue', 'Purple', 'Brown', 'Maroon')
facil_choices = ('Kitchen', 'Shower', 'Room', 'Den', 'Patio')
test_report = Test_Output()
test_report.init_report('Test_Report')
for i in range(10):
test_report.add_report_record(
Test_record(
Facility = random.choice(facil_choices),
Test_group = int(random.random() * 10**3),
Test_number = i,
Description = random.choice(desc_choices),
Result = random.choice((0,8)),
Execution_time = int(random.random() * 10**3),
Information = random.choice(info_choices),
Output = ''
)
)
test_report.write_report(display_report = True)
`
import os, sys
import webbrowser
import platform
from tempfile import gettempdir
from datetime import datetime
from collections import namedtuple
from timeit import default_timer as timer
DEFAULT_SCREEN_STACK_SIZE = 20
FILE_LINK = "file:///"
HTML_HEADER = """\
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
""".splitlines()
HTML_TRAILER = """\
</body>
</html>
""".splitlines()
field_names = [
'Facility', 'Test_group', 'Test_number',
'Description', 'Result', 'Execution_time',
'Information', 'Output'
]
Test_record = namedtuple('Test_record', field_names )
def _write_HTML_header(fp):
for line in HTML_HEADER: fp.write(line)
def _write_HTML_trailer(fp):
for line in HTML_TRAILER: fp.write(line)
def return_seconds_as_h_m_s(seconds):
'''
return tuple h, m, s representing hours, minutes, seconds
'''
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
return h, m, s
class Test_Output:
'''
Manage and generate test output data
'''
def __init__(self):
self.test_output_dir = None
self.test_output = None
self.screen_trace_stack = []
self.screen_trace_stack_size = DEFAULT_SCREEN_STACK_SIZE
self.output_records = []
self.report_start = 0
self.init_output()
def init_output(self):
'''
Initialized test output area
'''
self.test_output = []
self.screen_trace_stack = []
def _format_text_html(self, text, size = None):
'''
format text to html
'''
#
# TODO add HTML text formatting: color, font, size
#
if isinstance(text,str):
text = text.splitlines()
#
# add html new line tag
#
if size is None:
text_size = 30
return ['<p style="font-size:{0}px">'.format(text_size)] + \
[ line + '<br>' for line in text] + \
['</p>']
def add_text(self, text, size = None):
'''
Add text to test output
'''
self.test_output += self._format_text_html(text, size = size)
def add_screen_trace_stack(self, screen):
''' Add screen print to screen stack
'''
self.screen_trace_stack.append(screen)
if (
len(self.screen_trace_stack)
==
self.screen_trace_stack_size*3
):
self.screen_trace_stack = self.screen_trace_stack[
-self.screen_trace_stack_size:
]
def _write_screen_trace_stack(self, fp):
for screen in self.screen_trace_stack[
-self.screen_trace_stack_size:
]:
for line in screen:
fp.write(line.encode('ascii', 'ignore').decode() + '\n')
def add_screen(self, screen):
'''
Add screen print to test output. screen is a list of data
no html header should be included in screen
'''
#
# slice out html header and trailer
#
self.test_output += screen
def write_file(self, filename):
'''
Write test output created. '.htm' is appended to filename
'''
#
# Add html trailer
#
if self.test_output_dir is None:
self.set_dir('Test_Output')
os.makedirs(self.test_output_dir, exist_ok = True)
full_filename = self.test_output_dir + os.sep + filename + '.htm'
with open(full_filename, 'w') as fp:
_write_HTML_header(fp)
for line in self.test_output:
fp.write(line.encode('ascii', 'ignore').decode() + '\n')
fp.write(
''.join(
self._format_text_html(
'Screen trace stack. Size = {}'
.format(self.screen_trace_stack_size)
)
)
)
self._write_screen_trace_stack(fp)
_write_HTML_trailer(fp)
print('Test output written to: ' + full_filename)
return full_filename
def set_dir(self, prefix_dir = None):
'''
Set output direcory
'''
self.test_output_dir = (
gettempdir()
+ os.sep
+ (
'' if prefix_dir is None
else prefix_dir
)
+ os.sep
+ 'D'
+ datetime
.strftime(datetime.now(), '%Y%m%d')
+ os.sep
+ 'T'
+ datetime
.strftime(datetime.now(), '%H%M%S')
)
def init_report(self, prefix_dir = None):
'''
initialize data for report
'''
self.output_records = []
# set output directory
self.set_dir(prefix_dir)
self.report_start = timer()
def add_report_record(self, *args, **kwargs):
'''
Add report record information. All parameters from this list
must be specified:
'''
# Accept Test_record as one parameter
if len(args) == 1 and isinstance(args[0], Test_record):
self.output_records.append(args[0])
# other wise accept field from tuple as parm
else:
tuple_parms = ""
for fn in field_names:
tuple_parms += fn + " = kwargs['" + fn + "'], "
self.output_records.append(eval("Test_record(" + tuple_parms +
")"
)
)
def write_report(self, display_report = True):
'''
Write report, calculate total count, failed, and total report time
'''
report_end = timer()
test_count = fail_count = skip_count = 0
html_output = """ \
<!DOCTYPE html>
<html>
<head>
<style>
td {
width: 200px;
height: 60px;
}
th {
cursor: pointer;
}
</style>
</head>
<body>
<table border="1" id="myTable">
<thead>
<tr>
<th onclick="sortTable(0)">Facility</th>
<th onclick="sortTable(1)">Test_group</th>
<th onclick="sortTable(2)">Test_number</th>
<th onclick="sortTable(3)">Description</th>
<th onclick="sortTable(4)">Result</th>
<th onclick="sortTable(5)">Execution_time</th>
<th onclick="sortTable(6)">Information</th>
<th onclick="sortTable(7)">Output</th>
""".splitlines()
#
# add column headers
#
#for fn in field_names:
#html_output.append("<th>" + fn + "</th>")
html_output += """ \
</tr>
</thead>
<tbody>
""".splitlines()
#
# Create table with test information records
#
for tr in self.output_records:
test_count += 1
new_row = '<tr>'
for fn in field_names:
if fn == 'Result':
if tr.Result > 4:
fail_count += 1
output_value = 'Fail'
elif tr.Result == 4:
skip_count += 1
output_value = 'Skipped'
else:
output_value = 'Success'
elif fn == 'Output':
output_value = ''
if tr.Output != '':
output_value = '<a target="_blank" href=' + \
FILE_LINK + tr.Output + \
' style="display:block;">Output</a>'
elif fn == 'Execution_time':
output_value = ('%d:%02d:%02d' %
return_seconds_as_h_m_s(tr.Execution_time)
)
else:
output_value = eval('str(tr.' + fn + ')')
new_row += '<td>' + output_value + '</td>'
new_row += '</tr>'
html_output.append(new_row)
html_output += self._format_text_html(
"Total tests: %d. Failed tests: %d. Skipped tests: %d."
% (test_count, fail_count, skip_count)
)
html_output += self._format_text_html(
'Report test time %d:%02d:%02d' %
return_seconds_as_h_m_s(report_end -
self.report_start))
html_output += """ \
</tbody>
</table>
<script>
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("myTable");
switching = true;
dir = "asc";
while (switching) {
switching = false;
rows = table.getElementsByTagName("TR");
for (i = 1; i < (rows.length -1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i+1].getElementsByTagName("TD")[n];
if (dir == "asc") {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
} else if (dir == "desc") {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
switchcount ++;
} else {
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}
}
}
}
</script>
<script>
function resultFormatting() {
var rows = document.getElementById("myTable").getElementsByTagName('tr');
for(var i = 0; rows[0].children[i].innerHTML === "Result" || i < rows[0].children.length; i++);
for(var j = 1; j < rows.length; j++) {
rows[k].classList.add(rows[j].children[i].innerHTML === "Success" ? 'selected' : 'bad');
}
});
.selected{
background-color: #008000;
}
.bad{
background-color: #FF0000;
}
</script>
</body>
</html>
""".splitlines()
#
# create and write report file
#
os.makedirs(self.test_output_dir, exist_ok = True)
full_filename = self.test_output_dir + os.sep + 'test_report.htm'
with open(full_filename, 'w') as fp:
for line in html_output: fp.write(line + '\n')
if display_report:
#
# Check if mac os X
#
webbrowser.open(FILE_LINK + full_filename)
#
# Return full filename of report
#
return full_filename
推荐答案
因此,添加表行时需要添加其他逻辑:
So you'll need to add additional logic when you add your table rows:
#
# Create table with test information records
#
for tr in self.output_records:
test_count += 1
new_row, row_result = '', None #Modified
for fn in field_names:
if fn == 'Result':
if tr.Result > 4:
fail_count += 1
output_value, row_result = 'Fail', False #Modified
elif tr.Result == 4:
skip_count += 1
output_value = 'Skipped'
else:
output_value, row_result = 'Success', True #Modified
elif fn == 'Output':
output_value = ''
if tr.Output != '':
output_value = '<a target="_blank" href=' + \
FILE_LINK + tr.Output + \
' style="display:block;">Output</a>'
elif fn == 'Execution_time':
output_value = ('%d:%02d:%02d' %
return_seconds_as_h_m_s(tr.Execution_time)
)
else:
output_value = str(getattr(tr, fn)) #Modified
new_row += '<td>' + output_value + '</td>'
#Added new line
result_class = '' if row_result is None else ' class="{0}"'.format('selected' if row_result else 'bad')
new_row = '<tr{0}>{1}</tr>'.format(result_class, new_row) #Modified
html_output.append(new_row)
我引入了另一个变量row_result
,该变量将跟踪通过或失败的行.计算完该值后,您可以将该值添加到行类(<tr class=""
)中,以风格化该行的输出.
I introduced another variable row_result
that will keep track of rows that pass or fail. Once that has been calculated, you can add that value to the row class (<tr class=""
) to stylize that row's output.
为便于记录,最好使用 join
方法.另外,对于更简洁的方法,您可以使用 .format
建立每条线.您可以在线上看到很多证据.
For the record, string building in loops is best accomplised by using the join
method. Also, for a cleaner approach you can use .format
to build out each line. You can see lots of evidence online.
最后,如果可以避免,请不要使用eval
.它可以轻松引入漏洞.对于您的情况,可以使用 getattr
来获取变量tr
中的参数名称.
Finally, don't use eval
if you can avoid it. It can easily introduce vulnerabilities. For your case, you can use getattr
to get the variable parameter name from tr
.
这篇关于使用python的条件格式html表行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!