Controlling the styling of BootStrap form in Flask WTForms - python

I have a form where there are 14 questions, 4 option for each question, 1 correct answer, and a timer field that has to be rendered on the page something like this:
Expected form format
Help me in understanding and using WTFroms along with bootstrap to make my form look like this:
Currently, this is how it looks:
Current form format
Code for 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')
Code for 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's grid system works based on a 12 column system.
So for example, if you had 2 elements you wanted to display in the same row and give both an equal amount of space, you would give each of them 6 of the columns, each.
e.g. ->
<div class="row>
<h1 class="col-md-6">Hello</h1>
<h1 class="col-md-6">World</h1>
</div>
In your case where you needed to split up 8 pieces (4 answer labels, and 4 form boxes), it gets a bit more complex.
Once you give a DIV a set amount of the columns, inside that div, you distribute it based on the 12 column system still, even if 12 are not actually available.
Let's look at how I solved it in the solution I sent you below.
I started with putting half of the elements nested inside a div with class "col-md-6 row"
And the other half with the same.
Now when we are looking inside one of those halves, the moment we are nested inside, we are distribute those 6 columns based on the 12 grid system again.
So for example I could have given each of the 4 elements 3 each, class="col-md-3".
But since it seemed that you wanted the form field a bit larger than the text field, I went w/ "col-md-4" for the form fields and "col-md-2" for the text fields.
Here is what the solution looks like on my end -> https://imgur.com/gallery/ylMWjFN
I had to throw together an entire application to solve this so I went ahead and threw it on github for you if you want to look at the code there -> https://github.com/CraftyClark/ontrolling-the-styling-of-bootstrap-form-in-flask-wtforms/tree/main/application
Cheers,
{% 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 %}

Related

implementing admin.stackedinline in frontend

I have an inlineformset_factory: PollFormset = inlineformset_factory(Post, Poll, form=PollForm, max_num=10, extra=1, can_delete=False) and I want below the form the option to add and create another Poll like in the django admin panel,
template:
{% for form in poll_form %}
{{ form.non_field_errors }}
<div class="container" id="poll_form">
<div class="row" name="service_form">
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form %}
<div class="col-sm">
{{ field.errors }}
{{ field|as_crispy_field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endfor %}
I also tried {{poll_form.management_form}} but it doesnt work.

Django 'endfor', expected 'endblock'

I am attempting to learn Django but keep receiving the error " 'endfor', expected 'endblock'. Did you forget to register or load this tag? " when I add the {% for key,value in
price.DISPLAY.items %} {{ key }} {% endfor %} part of the code. How can I fix this? Any help would be great thanks.
home.html
{% extends 'base.html' %} {% block content %} {% for key,value in
price.DISPLAY.items %} {{ key }} {% endfor %}
<br />
<br />
{{ price.DISPLAY }}
<div class="jumbotron">
<h1 class="display-4">Welcome</h1>
</div>
<div class="container">
<div class="row">
{% for info in api.Data %}
<div class="card" style="width: 18rem">
<img src="{{info.imageurl}}" class="card-img-top" alt="{{info.source}}" />
<div class="card-body">
<h5 class="card-title">{{info.title}}</h5>
<p class="card-text">{{info.body}}</p>
<a href="{{info.url}}" class="btn btn-secondary" target="_blank"
>Read more</a
>
</div>
</div>
{% endfor %}
</div>
</div>
{{ api.Data }} {% endblock content %}
A template tag should not span multiple lines. You should write the {% for … %} tag on a single line:
{% extends 'base.html' %} {% block content %}
{% for key,value in price.DISPLAY.items %} {{ key }} {% endfor %}
…
{% endblock content %}

Javascript ID not showing reference to input text box - Django

{% extends 'halls/base.html' %}
{% block content %}
<div class="container">
<h2>Add Video to {{hall.title}}</h2>
<form method="post">
{% csrf_token %}
{% load widget_tweaks %}
{% for field in form %}
<div class="form-group {% if field.errors %} alert alert-danger {% endif %}">
{{ field.errors }}
{{ field.label_tag }}
{% render_field field class='form-control' %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary"> Add</button>
</form>
<br>
<h2>OR</h2>
<form>
{% for field in search_form %}
<div class="form-group ">
{{ field.errors }}
{{ field.label_tag }}
{% render_field field class='form-control' %}
</div>
{% endfor %}
</form>
<div id="search_results"></div>
<script type="text/javascript">
var delayTimer;
$("#id_search_term").keyup(function (){
clearTimeout(delayTimer);
$('#search_results').text('Loadingggg');
});
</script>
</div>
{% endblock %}
this is the HTML code. SO basically the whole idea here is when I inspect the search_form, it should give the id of the input box as "id_search_term". But when I inspect the box, it gives as id="id_search".
I am not able to find a way to reference the input box with the ID in the script tag

Auto-Populate a field in a form depending on a formula and previous field input

I am needing some help with Auto-Populating 2 fields on a form based on the input of the previous fields in that form from the user, all based on a formula. My entire web application works, just this functionality is confusing me and I do not know how to go about solving it. Please forgive me if this is a fairly easy/obvious approach.
Formula and Pricing Module
Other Instructions
models.py
routes.py: only showing that specific forms route
forms.py: showing only the Quote form
requestAQuote.html
{% extends "template.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Request a Quote today!</legend>
<div class="form-group">
{{ form.gallons_requested.label(class="form-control-label") }}
{% if form.gallons_requested.errors %}
{{ form.gallons_requested(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.gallons_requested.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.gallons_requested(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.delivery_date.label(class="form-control-label") }}
{% if form.delivery_date.errors %}
{{ form.delivery_date(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.delivery_date.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.delivery_date(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.request_date.label(class="form-control-label") }}
{% if form.request_date.errors %}
{{ form.request_date(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.request_date.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.request_date(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.delivery_location.label(class="form-control-label") }}
{% if form.delivery_location.errors %}
{{ form.delivery_location(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.delivery_location.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.delivery_location(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.delivery_contact_name.label(class="form-control-label") }}
{% if form.delivery_contact_name.errors %}
{{ form.delivery_contact_name(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.delivery_contact_name.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.delivery_contact_name(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.delivery_contact_phone.label(class="form-control-label") }}
{% if form.delivery_contact_phone.errors %}
{{ form.delivery_contact_phone(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.delivery_contact_phone.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.delivery_contact_phone(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.delivery_contact_email.label(class="form-control-label") }}
{% if form.delivery_contact_email.errors %}
{{ form.delivery_contact_email(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.delivery_contact_email.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.delivery_contact_email(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.suggested_price.label(class="form-control-label") }}
{% if form.suggested_price.errors %}
{{ form.suggested_price(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.suggested_price.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.suggested_price(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.total_amount_due.label(class="form-control-label") }}
{% if form.total_amount_due.errors %}
{{ form.total_amount_due(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.total_amount_due.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.total_amount_due(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.get_price(class="btn btn-outline-info") }}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% endblock content %}
you can add some javascript code to auto-populate it based on your other field.
please refer to this
Auto populate field base on what was entered in another field simultaneously

Displaying Django error messages in templates? - Not working

I have two forms login.html and register.html, and i follow the same methods for displaying errors in templates, but does not work.
login.html
<form method="post" action="" class="ui large form">
{% csrf_token %}
<div class="ui stacked segment">
{% if not form.non_field_errors %}
<div class="required field">
<label>Emailaddress</label>
{{ form.username }}
</div>
{% endif %}
{% if form.non_field_errors %}
<div class="required field error">
<label>Emailaddress</label>
{{ form.username }}
</div>
{% endif %}
{% if not form.non_field_errors %}
<div class="required field">
<label>Password</label>
{{ form.password }}
</div>
{% endif %}
{% if form.non_field_errors %}
<div class="required field error">
<label>Password</label>
{{ form.password }}
</div>
{% endif %}
<small><p>{{ form.non_field_errors }}</p></small>
<input type="submit" name="" class="ui fluid large teal submit button" value="login">
</div>
</form>
Output screenshots:
Non Error output
Error output
register.html
<form method="post" action="" class="ui large form">
{% csrf_token %}
<div class="ui stacked segment">
{% if not form.non_field_errors %}
<div class="required field">
<label>Emailaddress</label>
{{ form.email }}
</div>
{% endif %}
{% if form.non_field_errors %}
<div class="required field error">
<label>Emailaddress</label>
{{ form.email }}
<p>{{ form.email.errors }}</p>
</div>
{% endif %}
{% if not form.non_field_errors %}
<div class="required field">
<label>Password</label>
{{ form.password1 }}
</div>
{% endif %}
{% if form.non_field_errors %}
<div class="required field error">
<label>Password</label>
{{ form.password1 }}
<p>{{ form.password1.errors }}</p>
</div>
{% endif %}
{% if not form.non_field_errors %}
<div class="required field">
<label>Confirm Password</label>
{{ form.password2 }}
</div>
{% endif %}
{% if form.non_field_errors %}
<div class="required field error">
<label>Confirm Password</label>
{{ form.password2 }}
<p>{{ form.password2.errors }}</p>
</div>
{% endif %}
<small><p>{{ form.non_field_errors }}</p></small>
<input type="submit" name="" class="ui fluid large teal submit button" value="Sign Up">
</div>
</form>
This time i don't get any error messages displayed. What am i doing wrong?
non_field_errors(), as their name implies, show errors not associated with a field (docs).
Note that any errors raised by your Form.clean() override will not be associated with any field in particular. They go into a special “field” (called all), which you can access via the non_field_errors() method if you need to.
You shouldn't be using it as logic for whether a specific field has an error. You should be doing this:
{% if not form.email.errors %}
<div class="required field">
<label>Emailaddress</label>
{{ form.email }}
</div>
{% endif %}
and then in your login.html, you're not rendering {{ field.errors }} like you do in register.html:
{% if form.non_field_errors %}
<div class="required field error">
<label>Emailaddress</label>
{{ form.username }}
{# This is missing #}
<p>{{ form.username.errors }}</p>
</div>
{% endif %}

Categories