Problem
Your problem is that id not sent back to the server - only value is ... and since your flags do not have the value attribute, the default value is used, which, as it turned out, is t23>.
Since you noted this with wtforms , I will give you an example of how you could do this.
Never repeat this problem
There is a class in the WTForms documentation that will create a list of flags for you :
class MultiCheckboxField(SelectMultipleField): """ A multiple-select, except displays a list of checkboxes. Iterating the field will produce subfields, allowing custom rendering of the enclosed checkbox fields. """ widget = widgets.ListWidget(prefix_label=False) option_widget = widgets.CheckboxInput()
You should use this field in your user form as follows:
class FriendsForm(Form): potential_friends = MultiCheckboxField("Friends", coerce=int) # ... later ... @app.route("/add-friends", methods=["GET", "POST"]) def add_friends(): form = FriendsForm(request.form) # lookup friends, for now we'll use a static list form.potential_friends.choices = [(1, "Sam"), (2, "Joe")] # We'll also need a mapping of IDs to Person instances # (Made up for this example - use your own ;-) ) mapping = { 1: Person("Sam", profile_pic="sam.jpg"), 2: Person("Joe", profile_pic="joe.png") } if request.method == "POST": # Mark new friends return render_template("friends.html", form=form, persons=mapping)
Then in friends.html you can form.potential_friends over the form.potential_friends field:
{% for person in form.potential_friends %} persons[person.data].profile_pic :: {{person.label}} :: {{person}}<br> {% endfor %}
You can customize the HTML inside the for loop. My specific example should display (with a few attributes like for and name ):
sam.jpg :: <label>Sam</label> :: <input type="checkbox" value="1"> joe.png :: <label>Joe</label> :: <input type="checkbox" value="2">