Solution 1 :

You need to create a new ‘details’ list of tuples. In Python, you often can not change lists “in place”. If you just create a new ‘detail’ inside the for-loop, it will not get passed on to the ‘details’ list.

So, you need to replace the complete loop for detail in details: by the following line:

updated_details = [(user, VoteChoice, Comments, User.query.filter_by(name=user).first().fb_pic)
                   for (user, VoteChoice, Comments) in details]

At the end, you use these updated details to the returned render_template:

return render_template(..., vote_details=updated_details)

Solution 2 :

Tuples are immutable, so you cannot modify them directly.

Inside your for loop, make a list out of the original detail tuple, and append to that the additional value. Then, you can convert the list back to a tuple:

detail_list = list(detail)
detail_list += [maybe_existing_user.fb_pic]
detail = tuple(detail_list)

Solution 3 :

Repacking in one line with the splat operator

detail_list = *detail_list, maybe_existing_user.fb_pic

For example, in a python3 shell:

>>> detail_list = ("cat", "dog")
>>> detail_list = *detail_list, "rabbit"
>>> detail_list
('cat', 'dog', 'rabbit')
>>> 

Solution 4 :

You are already adding to the tuple correctly. The problem is that detail += ... creates a new tuple rather than appending to the existing one in the details list (because tuples are immutable). When you print(detail) within the loop, it seems to be altered correctly, but if you were to print the whole list details you would see the tuples in there do not have the additional information.

One solution is to rebuild the details list with the new tuples.

def add_more_info(t):
    maybe_existing_user = User.query.filter_by(name=detail[0]).first()
    return t + (maybe_existing_user, )

details = [add_more_info(detail) for detail in details]

Another solution would be to convert all of the details to lists first. Then you can append to them.

details = [list(detail) for detail in details]
for detail in details:
    maybe_existing_user = User.query.filter_by(name=detail[0]).first()
    detail.append(maybe_existing_user)

Problem :

I have a tuple that passes 3 items to an HTML page, and I want it to pass a fourth. I’ve read online that to do that, I’d have to turn my tuple into a list, but I tried that, and still didn’t get anything (no errors, the objects just didn’t show up at the end). So I stashed it for clarity.

I’m trying to add “maybe_existing_user.fb_pic” to the “details” tuple.

PYTHON

@app.route('/results/<int:id>')
def results(id):
    rate = 0  # either 0 or num/total
    article_list_of_one = Article.query.filter_by(id=id)
    a_obj = article_list_of_one[0]

    avs_obj = retrieve_article_vote_summary(a_obj.id) # vote_summary is a list of [tuples('True', numOfTrue), etc]
    total_votes = avs_obj.getTotalVotes()
    vote_choices = []
    vote_choice_list = VoteChoice.getVoteChoiceList()
    for item in vote_choice_list: # looping over VoteChoice objects
        num = avs_obj.getVoteCount(item.choice)
        if total_votes > 0:        # protecting against no votes
            rate = num/total_votes 
        vote_choices.append([item.choice, item.color, num, rate*100, total_votes])

    details = avs_obj.getVoteDetails() # 10/02 - retrieve array of tuples [(user, VoteChoice, Comments)]
    print("Inside results(" + str(id) + "):")
    details_count = 0
    for detail in details:

        maybe_existing_user = User.query.filter_by(name=detail[0]).first()
        detail += (maybe_existing_user.fb_pic,)

        print(detail)
        #print("    " + str(details_count) + ": " + details[0] + " " + details[1] + " " + details[2])
        details_count += 1

    return render_template('results.html', title=a_obj.title, id=id,
                           image_url=a_obj.image_url, url=a_obj.url,
                           vote_choices=vote_choices, home_data=Article.query.all(),
                           vote_details=details)

HTML

<!DOCTYPE html>
<html>
<body>
{% for detail in vote_details %}
<strong>User:</strong> {{ detail[0] }} &nbsp; <strong>Vote:</strong> {{ detail[1] }} &nbsp; <strong>Comments:</strong> {{ detail[2] }}<br>
{{ detail[3] }}
{% endfor %}
</body>
</html>

Comments

Comment posted by JohanC

Sorry, I forgot to replace ‘detail[0]’ with ‘user’

Comment posted by codi6

Thanks, it seems to be almost working, but it’s adding the last item letter by letter? Here’s my console printing out the new list:(‘Name’, ‘Exaggerated’, ‘comment’, ‘h’, ‘t’, ‘t’, ‘p’, ‘s’, ‘:’, ‘/’, ‘/’, ‘p’, ‘l’, ‘a’, ‘t’, ‘f’, ‘o’, ‘r’, ‘m’, ‘-‘, ‘l’, ‘o’, ‘o’, ‘k’, ‘a’, ‘s’, ‘i’, ‘d’, ‘e’, ‘.’, ‘f’, ‘b’, ‘s’, ‘b’, ‘x’, ‘.’, ‘c’, ‘o’, ‘m’, ‘/’, ‘p’, ‘l’, ‘a’, ‘t’, ‘f’, ‘o’, ‘r’, ‘m’, ‘/’, ‘p’, ‘r’, ‘o’, ‘f’, ‘i’, ‘l’, ‘e’, ‘p’, ‘i’, ‘c’, ‘/’, ‘?’, ‘a’, ‘s’, ‘i’, ‘d’, ‘=’, ‘1’, ‘0’, ‘2’, ‘0’, ‘0’, ‘9’, ‘1’, ‘3’, ‘3’, ‘8’, ‘2’, ‘6’, ‘5’, ‘3’, ‘7’, ‘8’, ‘2’, ‘&’, )

Comment posted by codi6

That worked for the console print! Though it’s still not showing up on the HTML. Any ideas why that might be?

Comment posted by JohanC

@IlanaE.Strauss Well, that’s explained in my answer. Changing one detail tuple doesn’t help in what you want to achieve.

By