Issue
I need to create a row of radio buttons in wtforms. So:
buttons = RadioField(choices=[(0, 'Option1), (1, 'Option2'), (2, 'Option3')])
creates:
What I would like to get is:
Option1 Option2 Option3
(for some reason the actual radio buttons don't render here) Meaning instead of unordered list of buttons I'd like a row of radio buttons.
Before posting the question I have tried to solve the problem myself. After reading this post: How can WTForms RadioField generate html without <ul> and <li> tag? I have read about the widgets and buttons here: https://wtforms.readthedocs.io/en/stable/widgets.html#built-in-widgets and here: https://wtforms.readthedocs.io/en/stable/fields.html Seems there is a in-built widget: class wtforms.widgets.Input(input_type=None) that will probably solve the issue by not applying unordered list tags to radio buttons.
I have tried to apply it as follows:
buttons = RadioField(widget=Input(input_type='radio'), choices=[(0, 'Option1'), (1, 'Option2'), (2, 'Option3')])
but I only get the error: AttributeError: 'RadioField' object has no attribute '_value'
My question are:
- will the Input widget display my buttons as a row instead of a list ?
- how do I apply it properly ?
- if not is there any other solution to display the button how I want ?
Solution
TDLR:
All your 3 Q. are answered below:
- Steps:
- Pick the right way to show it.
- Style it to make it in-line.
- Check-out down below for how to do it properly.
from wtforms import widgets
Gender = RadioField('Gender', choices=[('M', 'Male'), ('F', 'Female')],
widget=widgets.TableWidget(with_table_tag=True) )
- Import widgets so you can access all the classes and use the class you want inside the widget arg.
Here I used the TableWidget class, you can use other stuff but also you can use table. Then in your static folder add a style.css and style your table. Make it show in one line (in-which the internet is flooded with) how you can style your table.
A bit of explanation and how I figured out:
You are actually in the right way.
I'm sure you used validators like this:
from wtforms import validators, ValidationError
class ContactForm(FlaskForm):
name = TextField("Student Name:", [
validators.Required("Plz enter your name.")])
or maybe like this:
from wtforms.validators import DataRequired
class RegistrationForm(FlaskForm):
username = StringField('Username',
validators=[DataRequired(), Length(min=2, max=20)])
And you probably understand how it works, if you want to use validators import them.
Now you might actually ask how is this related?
When you check out this link (you provided) about the Built-in widgets, it says:
class wtforms.widgets.ListWidget(html_tag='ul', prefix_label=True)
# Renders a list of fields as a ul or ol list.
and by checking the widgets.core module exactly the ListWidget Class (the source code)
class ListWidget(object):
def __init__(self, html_tag='ul', prefix_label=True):
assert html_tag in ('ol', 'ul')
self.html_tag = html_tag
self.prefix_label = prefix_label
So it checks(by assertion) for selecting either ul or li tags then if you don't want to use either(let's say table) you have to use another class.
- That means by default we are using
ulorliHTML tag and how can we change that?
Simple! The same way we did for validators, import the needed classes and change the needed parameter like this:
from wtforms import widgets
Gender = RadioField('Gender', choices=[('M', 'Male'), ('F', 'Female')],
widget=widgets.TableWidget(with_table_tag=True) )
In this example I change the ul or li to TableWidget, read about it in the doc here.
It will show as a table like this:
This image shows gender as RadioField with also other fields.
Later you can style the table maybe by adding an id or class and style it.
This's how it will look like in your templates (I'm using Bootstrap as well and planning to style the label and the input seperately):
<div class="custom-control custom-radio custom-control-inline ">
{{ form.Gender.label(class="custom-control-label") }}
{{ form.Gender() }}
</div>
You can also use Flask-Bootstrap, for example in the pic above age(an IntegerField) looks like this in template:
{% import "bootstrap/wtf.html" as wtf %}
.
.
.
<div class="form-group">
{{ wtf.form_field(form.Age, class='form-control', placeholder='Age') }}
</div>
This shows all the field in a form but sometimes you want the label alone and the rest alone to style it, so that's what I'm doing in the Gender RadioField.
Answered By - ShifraSec
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.