-
-
Save ectrimble20/468156763a1389a913089782ab0f272e to your computer and use it in GitHub Desktop.
{% extends "layout_new.html" %} | |
{% block content_main %} | |
<div class="content-section"> | |
<form method="POST" action=""> | |
{{ form.hidden_tag() }} | |
<fieldset class="form-group"> | |
<legend class="border-bottom mb-4">User Choices</legend> | |
{% if form.choices.errors %} | |
<div class="invalid-feedback"> | |
{% for error in form.choices.errors %} | |
<span>{{ error }}</span> | |
{% endfor %} | |
</div> | |
{% endif %} | |
{% for choice in form.choices %} | |
<div class="form-check"> | |
{{ choice(class="form-check-input") }} | |
{{ choice.label(class="form-check-label") }} | |
</div> | |
{% endfor %} | |
</fieldset> | |
<div class="form-group"> | |
{{ form.submit(class="btn btn-outline-info") }} | |
</div> | |
</form> | |
</div> | |
{% endblock content_main %} |
class MultiCheckboxField(SelectMultipleField): | |
widget = widgets.ListWidget(prefix_label=False) | |
option_widget = widgets.CheckboxInput() | |
class ExampleForm(FlaskForm): | |
choices = MultiCheckboxField('Routes', coerce=int) | |
submit = SubmitField("Set User Choices") |
@example.route("/example", methods=["GET", "POST"]) | |
def example(): | |
form = ExampleForm() | |
# populate the forms dynamically with the choices in the database | |
form.check_options.choices = [(c.id, c.desc) for c in Choices.query.all()] | |
# if it's a post request and we validated successfully | |
if request.POST and form.validate_on_submit(): | |
# get our choices again, could technically cache these in a list if we wanted but w/e | |
c_records = Choices.query.all() | |
# need a list to hold our choices | |
accepted = [] | |
# looping through the choices, we check the choice ID against what was passed in the form | |
for choice in c_records: | |
# when we find a match, we then append the Choice object to our list | |
if choice.id in form.check_options.data: | |
accepted.append(choice) | |
# now all we have to do is update the users choices records | |
user.choices = accepted | |
db.session.add(user) | |
db.session.commit(user) | |
else: | |
# tell the form what's already selected | |
form.choices.data = [c.id for c in user.choices] | |
return render_template('example.html', form=form) | |
user_choices = app_db.Table('user_choices', | |
app_db.Column('user_id', app_db.Integer, app_db.ForeignKey('user.id'), primary_key=True), | |
app_db.Column('choice_id', app_db.Integer, app_db.ForeignKey('choice.id'), primary_key=True) | |
) | |
class User(db.Model, UserMixin): | |
id = app_db.Column(app_db.Integer, primary_key=True) | |
# other stuff as required | |
choices = db.relationship('Choices', secondary=user_choices, lazy='subquery' | |
backref=db.backref('users_choice', lazy=True)) | |
class Choices(db.Model): | |
id = app_db.Column(app_db.Integer, primary_key=True) | |
desc = app_db.Column(app_db.String(25), nullable=False) |
This is very helpful, thanks
Hi, thanks for the example. One thing I can't fully comprehend is: where did that form.check_options.choices
come from? It looks like it should've been belong to the form.py but I can't quite figure out how. Could you please elaborate?
Hi, thanks for the example. One thing I can't fully comprehend is: where did that
form.check_options.choices
come from? It looks like it should've been belong to the form.py but I can't quite figure out how. Could you please elaborate?
Had to go dig around in my old code to figure out what was going on here as I haven't touched this code in quite some time, I think check_options
is a typo or a renaming that didn't make it throughout the example. I believe it's actually suppose to be form.choices.choices
based on the ExampleForm class as it's suppose to be reference to the selected options from the forms MultiCheckboxField which is choices = MultiCheckboxField('Routes', coerce=int)
in the example code. Thinking about it now, chances are when I was copying the code to make this little reference, I changed the name from choices.choices
to check_options.choices
because it looked weird with choices.choices
.
A more complete example is in my FlaskProductSiteDemo repo on Github. The domain/admin/routes.py
and domain/admin/forms.py
has a clearer naming example that doesn't have a random name appear out of the blue.
I believe it's actually suppose to be
form.choices.choices
based on the ExampleForm class as it's suppose to be reference to the selected options from the forms MultiCheckboxField which ischoices = MultiCheckboxField('Routes', coerce=int)
in the example code. Thinking about it now, chances are when I was copying the code to make this little reference, I changed the name fromchoices.choices
tocheck_options.choices
because it looked weird withchoices.choices
.
I guess that makes sense, yeah. Thanks for the quick reply.
A more complete example is in my FlaskProductSiteDemo repo on Github. The
domain/admin/routes.py
anddomain/admin/forms.py
has a clearer naming example that doesn't have a random name appear out of the blue.
I'll definitely check it.
Very useful, thank you!
This was helpful. Thanks!
Can't say enough about how much this helped me! As a note to others, I had to import "widgets" from wtforms.
# tell the form what's already selected
form.choices.data = [c.id for c in user.choices]
Thanks! 👍
Very valuable. Thanks a lot!
How to set attributes (key and value) to each checkbox?
Sorry to anyone who stumbles on this, I didn't include imports or any fluff. This is some example code I'm jotting down for my own reference which handles multiple selections using check boxes since isn't a good solution for all options in which you wish to assign certain values (e.g a User Access Control setup where you want to check off allowed actions for a specific user). Note that a lot of this was C&P from a demo project I'm doing with Flask, so some names might be incorrect and the code might not function 100% out of the box, but if anything, I hope this helps anyone who was stuck on this problem as I was.