使用python的条件格式html表行

时间:2018-07-30 18:47:32

标签: javascript python python-3.x html-table

我必须有条件地格式化用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

1 个答案:

答案 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。对于您的情况,可以使用getattrtr获取变量参数名称。