使用python的条件格式html表行 [英] Conditional format html table rows with python

查看:71
本文介绍了使用python的条件格式html表行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆