在 Flask WTForms 中控制 BootStrap 表单的样式
Controlling the styling of BootStrap form in Flask WTForms
我有一个表格,其中有 14 个问题,每个问题有 4 个选项,1 个正确答案,以及一个必须在页面上呈现的计时器字段,如下所示:
Expected form format
帮助我理解和使用 WTFroms 以及 bootstrap 让我的表单看起来像这样:
目前,它是这样的:
Current form format
forms.py
的代码:
class XMLQuestionForm(FlaskForm):
question = FieldList(StringField('Question', validators=[DataRequired(), Length(max=395)]), min_entries=14, max_entries=14 )
optionA = FieldList(StringField('Option A', validators=[DataRequired(), Length(max=85)]), min_entries=14, max_entries=14)
optionB = FieldList(StringField('Option B', validators=[DataRequired(), Length(max=85)]), min_entries=14, max_entries=14)
optionC = FieldList(StringField('Option C', validators=[DataRequired(), Length(max=85)]), min_entries=14, max_entries=14)
optionD = FieldList(StringField('Option D', validators=[DataRequired(), Length(max=85)]), min_entries=14, max_entries=14)
answer = FieldList(SelectField('Answer', validators=[DataRequired()], choices=[(None,'<Select an answer>'),('Option A','Option A'),('Option B','Option B'),('Option C','Option C'),('Option D','Option D')]), min_entries=14, max_entries=14)
timer = FieldList(IntegerField('Timer', default=60), min_entries=14, max_entries=14)
submit = SubmitField('Generate XML')
home.html
的代码
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">KBC Question XML Creator</legend>
{% for n in range(14) %}
<!-- Question -->
{% if form.question[n].errors %}
{{ form.question[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.question[n].label }} {{ loop.index }} {{ form.question[n](class="form-control form-control-lg") }}
{% endif %}
<!-- Options -->
{% if form.optionA[n].errors %}
{{ form.optionA[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionA[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.optionA[n].label }} {{ form.optionA[n](class="form-control col-sm-2") }}
{% endif %}
{% if form.optionB[n].errors %}
{{ form.optionB[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionB[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.optionB[n].label }} {{ form.optionB[n](class="form-control col-sm-2") }}
{% endif %}
{% if form.optionC[n].errors %}
{{ form.optionC[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionC[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.optionC[n].label }} {{ form.optionC[n](class="form-control col-sm-2") }}
{% endif %}
{% if form.optionD[n].errors %}
{{ form.optionD[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionD[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.optionD[n].label }} {{ form.optionD[n](class="form-control col-sm-2") }}
{% endif %}
<!-- Answer -->
{% if form.answer[n].errors %}
{{ form.answer[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.answer[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.answer[n].label }} {{ form.answer[n](class="form-control col-sm-4") }}
{% endif %}
<!-- Timer -->
{% if form.timer[n].errors %}
{{ form.timer[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.timer[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.timer[n].label }} {{ form.timer[n](class="form-control col-sm-4") }}
{% endif %}
<hr>
{% endfor %}
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% endblock content %}
Bootstrap 的网格系统基于 12 列系统工作。
因此,例如,如果您有 2 个元素,您希望在同一行中显示并给两个元素等量的 space,您将为每个元素提供 6 列。
例如->
<div class="row>
<h1 class="col-md-6">Hello</h1>
<h1 class="col-md-6">World</h1>
</div>
在您需要拆分 8 个部分(4 个答案标签和 4 个表单框)的情况下,它会变得有点复杂。
一旦你给 DIV 一定数量的列,在 div 中,你仍然基于 12 列系统分配它,即使 12 列实际上不可用。
下面我发给你的解决方案,看看我是怎么解决的。
我开始将一半的元素嵌套在 div 中 class "col-md-6 row"
和另一半一样。
现在,当我们查看其中一个部分的内部时,当我们嵌套在其中时,我们将再次根据 12 网格系统分配这 6 列。
因此,例如,我可以给 4 个元素中的每个元素 3 个元素,class="col-md-3"。
但是由于您似乎希望表单字段比文本字段大一点,所以我为表单字段使用了“col-md-4”,为文本字段使用了“col-md-2”。
这是我这边的解决方案 -> https://imgur.com/gallery/ylMWjFN
我不得不将整个应用程序放在一起来解决这个问题,所以我继续将它放在 github 上,如果您想查看那里的代码 -> https://github.com/CraftyClark/ontrolling-the-styling-of-bootstrap-form-in-flask-wtforms/tree/main/application
干杯,
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">KBC Question XML Creator</legend>
{% for n in range(14) %}
<div class="row col-md-10">
<!-- Question -->
{% if form.question[n].errors %}
{{ form.question[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.question[n].label }} {{ loop.index }} {{ form.question[n](class="form-control form-control-lg") }}
{% endif %}
</div>
<br>
<!-- start of options row -->
<div class="row">
<!-- Options -->
<div class="col-md-6 row">
{% if form.optionA[n].errors %}
{{ form.optionA[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionA[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
<div class="form-group col-md-2">
{{ form.optionA[n].label(class="form-control-label") }}
</div>
<div class="form-group col-md-4">
{{ form.optionA[n](class="form-control form-control-lg") }}
</div>
{% endif %}
{% if form.optionB[n].errors %}
{{ form.optionB[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionB[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
<div class="form-group col-md-2">
{{ form.optionB[n].label(class="form-control-label") }}
</div>
<div class="form-group col-md-4">
{{ form.optionB[n](class="form-control form-control-lg") }}
</div>
{% endif %}
</div>
<div class="col-md-6 row">
{% if form.optionC[n].errors %}
{{ form.optionC[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionC[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
<div class="form-group col-md-2">
{{ form.optionC[n].label(class="form-control-label") }}
</div>
<div class="form-group col-md-4">
{{ form.optionC[n](class="form-control form-control-lg") }}
</div>
{% endif %}
{% if form.optionD[n].errors %}
{{ form.optionD[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionD[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
<div class="form-group col-md-2">
{{ form.optionD[n].label(class="form-control-label") }}
</div>
<div class="form-group col-md-4">
{{ form.optionD[n](class="form-control form-control-lg") }}
</div>
{% endif %}
</div>
</div>
<!-- end of options row -->
<!-- Answer -->
{% if form.answer[n].errors %}
{{ form.answer[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.answer[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.answer[n].label }} {{ form.answer[n](class="form-control col-sm-4") }}
{% endif %}
<!-- Timer -->
{% if form.timer[n].errors %}
{{ form.timer[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.timer[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.timer[n].label }} {{ form.timer[n](class="form-control col-sm-4") }}
{% endif %}
<hr>
{% endfor %}
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% endblock content %}
我有一个表格,其中有 14 个问题,每个问题有 4 个选项,1 个正确答案,以及一个必须在页面上呈现的计时器字段,如下所示:
Expected form format
帮助我理解和使用 WTFroms 以及 bootstrap 让我的表单看起来像这样:
目前,它是这样的:
Current form format
forms.py
的代码:
class XMLQuestionForm(FlaskForm):
question = FieldList(StringField('Question', validators=[DataRequired(), Length(max=395)]), min_entries=14, max_entries=14 )
optionA = FieldList(StringField('Option A', validators=[DataRequired(), Length(max=85)]), min_entries=14, max_entries=14)
optionB = FieldList(StringField('Option B', validators=[DataRequired(), Length(max=85)]), min_entries=14, max_entries=14)
optionC = FieldList(StringField('Option C', validators=[DataRequired(), Length(max=85)]), min_entries=14, max_entries=14)
optionD = FieldList(StringField('Option D', validators=[DataRequired(), Length(max=85)]), min_entries=14, max_entries=14)
answer = FieldList(SelectField('Answer', validators=[DataRequired()], choices=[(None,'<Select an answer>'),('Option A','Option A'),('Option B','Option B'),('Option C','Option C'),('Option D','Option D')]), min_entries=14, max_entries=14)
timer = FieldList(IntegerField('Timer', default=60), min_entries=14, max_entries=14)
submit = SubmitField('Generate XML')
home.html
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">KBC Question XML Creator</legend>
{% for n in range(14) %}
<!-- Question -->
{% if form.question[n].errors %}
{{ form.question[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.question[n].label }} {{ loop.index }} {{ form.question[n](class="form-control form-control-lg") }}
{% endif %}
<!-- Options -->
{% if form.optionA[n].errors %}
{{ form.optionA[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionA[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.optionA[n].label }} {{ form.optionA[n](class="form-control col-sm-2") }}
{% endif %}
{% if form.optionB[n].errors %}
{{ form.optionB[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionB[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.optionB[n].label }} {{ form.optionB[n](class="form-control col-sm-2") }}
{% endif %}
{% if form.optionC[n].errors %}
{{ form.optionC[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionC[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.optionC[n].label }} {{ form.optionC[n](class="form-control col-sm-2") }}
{% endif %}
{% if form.optionD[n].errors %}
{{ form.optionD[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionD[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.optionD[n].label }} {{ form.optionD[n](class="form-control col-sm-2") }}
{% endif %}
<!-- Answer -->
{% if form.answer[n].errors %}
{{ form.answer[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.answer[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.answer[n].label }} {{ form.answer[n](class="form-control col-sm-4") }}
{% endif %}
<!-- Timer -->
{% if form.timer[n].errors %}
{{ form.timer[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.timer[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.timer[n].label }} {{ form.timer[n](class="form-control col-sm-4") }}
{% endif %}
<hr>
{% endfor %}
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% endblock content %}
Bootstrap 的网格系统基于 12 列系统工作。 因此,例如,如果您有 2 个元素,您希望在同一行中显示并给两个元素等量的 space,您将为每个元素提供 6 列。 例如->
<div class="row>
<h1 class="col-md-6">Hello</h1>
<h1 class="col-md-6">World</h1>
</div>
在您需要拆分 8 个部分(4 个答案标签和 4 个表单框)的情况下,它会变得有点复杂。 一旦你给 DIV 一定数量的列,在 div 中,你仍然基于 12 列系统分配它,即使 12 列实际上不可用。
下面我发给你的解决方案,看看我是怎么解决的。 我开始将一半的元素嵌套在 div 中 class "col-md-6 row" 和另一半一样。 现在,当我们查看其中一个部分的内部时,当我们嵌套在其中时,我们将再次根据 12 网格系统分配这 6 列。 因此,例如,我可以给 4 个元素中的每个元素 3 个元素,class="col-md-3"。 但是由于您似乎希望表单字段比文本字段大一点,所以我为表单字段使用了“col-md-4”,为文本字段使用了“col-md-2”。
这是我这边的解决方案 -> https://imgur.com/gallery/ylMWjFN
我不得不将整个应用程序放在一起来解决这个问题,所以我继续将它放在 github 上,如果您想查看那里的代码 -> https://github.com/CraftyClark/ontrolling-the-styling-of-bootstrap-form-in-flask-wtforms/tree/main/application
干杯,
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">KBC Question XML Creator</legend>
{% for n in range(14) %}
<div class="row col-md-10">
<!-- Question -->
{% if form.question[n].errors %}
{{ form.question[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.question[n].label }} {{ loop.index }} {{ form.question[n](class="form-control form-control-lg") }}
{% endif %}
</div>
<br>
<!-- start of options row -->
<div class="row">
<!-- Options -->
<div class="col-md-6 row">
{% if form.optionA[n].errors %}
{{ form.optionA[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionA[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
<div class="form-group col-md-2">
{{ form.optionA[n].label(class="form-control-label") }}
</div>
<div class="form-group col-md-4">
{{ form.optionA[n](class="form-control form-control-lg") }}
</div>
{% endif %}
{% if form.optionB[n].errors %}
{{ form.optionB[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionB[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
<div class="form-group col-md-2">
{{ form.optionB[n].label(class="form-control-label") }}
</div>
<div class="form-group col-md-4">
{{ form.optionB[n](class="form-control form-control-lg") }}
</div>
{% endif %}
</div>
<div class="col-md-6 row">
{% if form.optionC[n].errors %}
{{ form.optionC[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionC[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
<div class="form-group col-md-2">
{{ form.optionC[n].label(class="form-control-label") }}
</div>
<div class="form-group col-md-4">
{{ form.optionC[n](class="form-control form-control-lg") }}
</div>
{% endif %}
{% if form.optionD[n].errors %}
{{ form.optionD[n](class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.optionD[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
<div class="form-group col-md-2">
{{ form.optionD[n].label(class="form-control-label") }}
</div>
<div class="form-group col-md-4">
{{ form.optionD[n](class="form-control form-control-lg") }}
</div>
{% endif %}
</div>
</div>
<!-- end of options row -->
<!-- Answer -->
{% if form.answer[n].errors %}
{{ form.answer[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.answer[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.answer[n].label }} {{ form.answer[n](class="form-control col-sm-4") }}
{% endif %}
<!-- Timer -->
{% if form.timer[n].errors %}
{{ form.timer[n](class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.timer[n].errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.timer[n].label }} {{ form.timer[n](class="form-control col-sm-4") }}
{% endif %}
<hr>
{% endfor %}
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% endblock content %}