我必须有条件地格式化用Python生成的html表的行。我以前不得不对表列进行排序,并使用javascript进行了排序。而不是有条件地格式化html行上的background-color,我如何修改Python代码来做到这一点? “结果”行是“成功”,然后行是绿色,哪里行是“失败”,然后行是红色?该代码段显示了我如何尝试仅使用js来执行此操作。代码是2个py文件,js代码位于代码 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
答案 0 :(得分:0)
因此,在添加表行时,您需要添加其他逻辑:
#
# 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=""
)中,以风格化该行的输出。
为便于记录,最好使用join
方法来实现循环中的字符串构建。另外,对于更简洁的方法,您可以使用.format
来构建每行。您可以在线看到许多evidence。
最后,如果可以避免使用,请不要使用eval
。它可以easily introduce vulnerabilities。对于您的情况,可以使用getattr
从tr
获取变量参数名称。