首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用python的条件格式html表行

使用python的条件格式html表行
EN

Stack Overflow用户
提问于 2018-07-31 02:47:32
回答 1查看 1K关注 0票数 0

我必须有条件地格式化一个用Python生成的html表格的行。以前,我必须对表列进行排序,并使用javascript来实现。我怎么才能修改Python代码来实现这一点呢?其中“结果”行是“成功”,那么行是绿色的,而行是“失败”的,那么行是红色的?代码片段显示了我如何尝试仅使用js来完成此任务。代码是2py文件,js代码是在代码末尾的函数resultFormating

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-31 03:10:42

因此,在添加表行时,需要添加额外的逻辑:

代码语言:javascript
复制
#
# 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,它将跟踪通过或失败的行。计算完成后,可以将该值添加到row类(<tr class="")中,以样式化该行的输出。

根据记录,在循环中构建字符串最好使用join方法。此外,对于更简洁的方法,您可以使用.format来构建每一行。你可以在网上看到很多evidence

最后,如果可以避免,请不要使用eval。它可以easily introduce vulnerabilities。对于您的情况,您可以使用getattrtr获取变量参数名称。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51600410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档