Question

I have a list of tuples, that I get from a sqlite3 database. I have tried to get the database differently without any luck, this is not the person of this question but ultimately if it helps format the description of my radio button form I will be ecstatic.

the list I have looks like:

images = [(1, u'True', u'file_Name.img', u'img', u'train', u'2013-02-0509:59:46.442660file.ext',
   u' file2.ext', u'ABC', u"[u'prod_one-prod_two']", u'name@email.com',
   u'nothing happens', u'2013-02-0509:59:46.442660', u"[u'ftp://link/file_Name.img', 
   u'ftp://link/file3.ext', u'ftp://link/file_Name.log']"),(2, u'True',u'file_Name.img', 
   u'img', u'train', u'2013-02-0509:59:46.442660file.ext', u' file2.ext', u'ABC', 
   u"[u'prod_one-prod_two']", u'name@email.com', u'nothing happens', 
   u'2013-02-0509:59:46.442660', u"[u'ftp://link/file_Name.img', 'ftp://link/file3.ext', 
   u'ftp://link/file_Name.log']")]

What I would like to do is have the value of the selection be the first element of each tuple

rows = [(str(x[0]), x) for x in images]
form.images.choices = rows

However it looks as if I just printed that mess with the unicode character and everything.

So I am trying to format it in a nice table so it is easy to see what each tuple contains

descriptionList = []
description = ''
for i in images:
    for j in i:
        description = description + '\t|' + str(j)
    descriptionList.append(description)


rows = [(str(x[0]), y) for x, y in zip(images, descriptionList)]
form.images.choices = rows

However it does not have the tab character in the output when I display the form.

So now I am thinking about passing descriptionList into the template and display it beside each radio box to act as a description in the form.

return render_template('database.html', form=form, descriptions = descriptionList)
{% for subfield, desc in zip(form.images, descriptions) %}
        <tr>
            <td>{{ subfield }}</td>
            {# {{ subfield.label }} (this is a comment)#}
            desc <br>
        </tr>
    {% endfor %}

However I get the error "UndefinedError: 'zip' is undefined"

and without it I get:

{% for subfield, desc in (form.images, descriptions) %}
ValueError: too many values to unpack

Any suggestions on how to solve this would be nothing short of amazing. Thanks

Was it helpful?

Solution

Let me start with a more simple image list to act as a cleaner example:

images = [
            (1, u'True', u'file_one.jpg', u'2013'),
            (2, u'False', u'file_two.jpg', u'2012'),
]

You then refine that list of tuples to be choices to use for the form values, essentially the goal is to provide a list of two value tuples to wtforms:

[
    (1,'file_one.jpg'), 
    (2,'file_two.jpg')
]

But you use this list comprehension:

rows = [(str(x[0]), x) for x in images]
form.images.choices = rows

Which will generate:

[
    (1, (1, u'True', u'file_one.jpg', u'2013')), 
    (2, (2, u'False', u'file_two.jpg', u'2012'))
]

Which isn't useful to wtforms, it doesn't know how to handle that tuple within a tuple. So you need to pick the value for the label, or format that data better.

So either alter your list comprehension to pick a better description, which will get you to the goal:

rows = [(x[0],x[2]) for x in images]

Or join all the data together to give a more.. verbose but potentially useful to you description:

rows = [(x[0], "\t|".join([str(y) for y in x])) for x in images]

Which will result in:

[
    (1, '1\t|True\t|file_one.jpg\t|2013'), 
    (2, '2\t|False\t|file_two.jpg\t|2012')
]

Read up more on list comprehensions.

OTHER TIPS

Try to prepare zip(form.images, descriptions) not in html template, but in python code and then send it to template:

   imgs_with_descriptions = zip(form.images, descriptionList)

in template:

   {% for subfield, desc in imgs_with_descriptions %}
       <tr>
            <td>{{ subfield }}</td>
            {# {{ subfield.label }} (this is a comment)#}
            desc <br>
        </tr>
   {% endfor %}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top