Search code examples
pythonhtmlweb2py

Web2Py - using starred expression for rendering HTML table


This question is an extension of: Web2Py - rendering AJAX response as HTML table

Basically, I come up with a dynamic list of response rows that I need to display on the UI as an HTML table.

Essentially the code looks like this,

response_results = []

row_one = ['1', 'Col 11', 'Col 12', 'Col 13']
response_results.append(row_one)

row_two = ['2', 'Col 21', 'Col 22', 'Col 23']
response_results.append(row_two)

html = DIV(TABLE(THEAD(TR(TH('Row #'), TH('Col 1'), TH('Col 2'), TH('Col 3')), 
                       _id=0), TR([*response for response in response_results]),
                 _id='records_table', _class='table table-bordered'),
           _class='table-responsive')
return html

When I use this kind of code: TR([request.vars[input] for input in inputs]) or TR(*the_list), it works fine.

However, I have come up with a need to use a hybrid of these two i.e. TR([*response for response in response_results]). But, it fails giving an error message:

"Python version 2.7 does not support this syntax. Starred expressions are not allowed as assignment targets in Python 2."

When I run this code instead i.e. without a '*': TR([response for response in response_results]) it runs fine but puts all the columns of my row together in the first column of the generated HTML table, leaving all other columns blank.

Can someone kindly help me resolve this issue and guide on how can I achieve the required result of displaying each column of the rows at their proper spots in the generated HTML table?


Solution

  • You need to generate a TR for each item in response_results, which means you need a list of TR elements with which you can then use Python argument expansion (i.e., the * syntax) to treat each TR as a positional argument to TABLE.

    html = DIV(TABLE(THEAD(TR(TH('Row #'), TH('Col 1'), TH('Col 2'), TH('Col 3')), _id=0),
                     *[TR(response) for response in response_results],
                     _id='records_table', _class='table table-bordered'),
               _class='table-responsive')
    

    Note, because each response is itself a list, you could also use argument expansion within the TR:

    *[TR(*response) for response in response_results]
    

    But that is not necessary, as TR optionally takes a list, converting each item in the list into a table cell.

    Another option is to make response_results a list of TR elements, starting with the THEAD element, and then just pass that list to TABLE:

    response_results = [THEAD(TR(TH('Row #'), TH('Col 1'), TH('Col 2'), TH('Col 3')), _id=0)]
    
    row_one = ['1', 'Col 11', 'Col 12', 'Col 13']
    response_results.append(TR(row_one))
    
    row_two = ['2', 'Col 21', 'Col 22', 'Col 23']
    response_results.append(TR(row_two))
    
    html = DIV(TABLE(response_results, _id='records_table', _class='table table-bordered'),
               _class='table-responsive')
    

    Again, you could do TABLE(*response_results, ...), but the * is not necessary, as TABLE can take a list of row elements.