Управление стилем начальной загрузки формы в Flask WTForms

#python #twitter-bootstrap #flask #wtforms

#python #twitter-bootstrap #flask #wtforms

Вопрос:

У меня есть форма, в которой есть 14 вопросов, 4 варианта для каждого вопроса, 1 правильный ответ и поле таймера, которое должно отображаться на странице примерно так:

Ожидаемый формат формы

Помогите мне понять и использовать WTFroms вместе с bootstrap, чтобы моя форма выглядела так:

В настоящее время это выглядит так:

Текущий формат формы

Код для 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 %}
 

Ответ №1:

Сеточная система Bootstrap работает на основе системы из 12 столбцов. Так, например, если у вас было 2 элемента, которые вы хотели отобразить в одной строке, и обоим отводилось одинаковое количество места, вы бы дали каждому из них по 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 с классом «col-md-6 row», а другой половины с тем же. Теперь, когда мы смотрим внутрь одной из этих половин, в тот момент, когда мы вложены внутрь, мы снова распределяем эти 6 столбцов на основе 12 grid-системы. Так, например, я мог бы присвоить каждому из 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 %}
 

Комментарии:

1. Это сделало свою работу. Отличное объяснение кода. Спасибо.