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 %}
{% 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
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
I am new to Django, and I am reading one app on github:
https://github.com/rogargon/myrecommendations/blob/web2-html/myrestaurants/urls.py#L18
There is one urlpattern like
url(r'^restaurants/(?P<pk>\d+)/$',
RestaurantDetail.as_view(),
name='restaurant_detail')
It revoke RestaurantDetail view, here: https://github.com/rogargon/myrecommendations/blob/master/myrestaurants/views.py#L36
class RestaurantDetail(DetailView):
model = Restaurant
template_name = 'myrestaurants/restaurant_detail.html'
def get_context_data(self, **kwargs):
context = super(RestaurantDetail, self).get_context_data(**kwargs)
context['RATING_CHOICES'] = RestaurantReview.RATING_CHOICES
return context
Here I know pk is set to one number indicating the id of restaurant, but in the html model, https://github.com/rogargon/myrecommendations/blob/master/myrestaurants/templates/myrestaurants/restaurant_detail.html, I didn't see any where using pk, but the page shows only the one restaurant. Could you how does pk work in this process? How the template know which restaurant I want to show? And why there is no return in this view?
{% extends "myrestaurants/base.html" %}
{% block title %}MyRestaurants - {{ restaurant.name }}{% endblock %}
{% block content %}
<span vocab="http://schema.org/" typeof="Restaurant">
<h1>
<span property="name">{{ restaurant.name }}</span>
{% if user == restaurant.user %}
(edit)
{% endif %}
</h1>
<h2>Address:</h2>
<p>
{{ restaurant.street }}, {{ restaurant.number }} <br/>
{{ restaurant.zipcode }} {{ restaurant.city }} <br/>
{{ restaurant.stateOrProvince }} ({{ restaurant.country }})
</p>
<h2>
Dishes
{% if user.is_authenticated %}
(add)
{% endif %}
</h2>
<ul>
{% for dish in restaurant.dishes.all %}
<li><a href="{% url 'myrestaurants:dish_detail' restaurant.id dish.id %}">
{{ dish.name }}</a></li>
{% empty %}<li>Sorry, no dishes for this restaurant yet.</li>
{% endfor %}
</ul>
<h2>Reviews</h2>
{% if restaurant.restaurantreview_set.all|length > 0 %}
<span rel="aggregateRating">
<p typeof="AggregateRating">
Average rating <span property="ratingValue">{{ restaurant.averageRating|stringformat:".1f" }}</span>
{% with restaurant.restaurantreview_set.all|length as reviewCount %}
from <span property="reviewCount">{{ reviewCount }}</span> review{{ reviewCount|pluralize }}
{% endwith %}
</p>
</span>
<ul rel="review">
{% for review in restaurant.restaurantreview_set.all %}
<li typeof="Review">
<p rel="reviewRating" typeof="Rating">
<span property="worstRating" content="{{ RATING_CHOICES.0.0 }}"></span>
<span property="ratingValue">{{ review.rating }}</span> star{{ review.rating|pluralize }}
{% with RATING_CHOICES|last as best %}
<span property="bestRating" content="{{ best.0 }}"></span>
{% endwith %}
</p>
<p property="description">{% if review.comment %}{{ review.comment }}{% endif %}</p>
<p>Created by <span property="author">{{ review.user }}</span> on
<span property="datePublished" content="{{ review.date|date:'Y-m-d' }}">{{ review.date }}</span></p>
</li>
{% endfor %}
</ul>
{% endif %}
</span>
<h3>Add Review</h3>
<form action="{% url 'myrestaurants:review_create' restaurant.id %}" method="post">
{% csrf_token %}
Message: <textarea name="comment" id="comment" rows="4"></textarea>
<p>Rating:</p>
<p>{% for rate in RATING_CHOICES %}
<input type="radio" name="rating" id="rating{{ forloop.counter }}" value="{{ rate.0 }}" />
<label for="choice{{ forloop.counter }}">{{ rate.1 }} star{{ rate.0|pluralize }}</label>
<br/>{% endfor %}
</p>
<input type="submit" value="Review" />
</form>
{% endblock %}
{% block footer %}
Created by {{ restaurant.user }} on {{ restaurant.date }}
{% endblock %}
The behavior you're asking about ("How the template know which restaurant I want to show") is view behavior, not template behavior.
The template renderer gets passed a restaurant value by the view. The view has no (explicit) return because it's a class-based view - a subclass of DetailView, in particular. DetailView itself inherits standard methods that this view does not override to accept a PK parameter and load a particular instance.
You can read the source code for DetailView to get more of a sense of what's going on, if you like, eg https://github.com/django/django/blob/master/django/views/generic/detail.py - but class-based views are a bit of an advanced topic, and not every project will even use them. I'd focus on other areas first.
i wonder how i can add some extra html to a certain field in a template in Django
I have the following form (forms.py)
first_name = forms.CharField(widget=forms.TextInput(attrs={'required': 'required'}))
last_name = forms.CharField(widget=forms.TextInput(attrs={'required': 'required'}))
street = forms.CharField(widget=forms.TextInput(attrs={'required': 'required'}))
In my template i get the fields with:
<form action="" method="post">{% csrf_token %}
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<input type="submit" value="Submit" />
</form>
Now i want to add some extra html to the street field like this
<form action="" method="post">{% csrf_token %}
{% for field in form %}
{% if field.type =='street' %}
<div class="fieldWrapper otherclass">
<hr>
{% else %}
<div class="fieldWrapper">
{% endif %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<input type="submit" value="Submit" />
</form>
The whole thing fails:
Could not parse the remainder: '=='street'' from '=='street''
Template operators require a space before and after so replace
{% if field.type =='street' %}
with
{% if field.type == 'street' %}
or use the ifequal templatetag
{% ifequal field.type 'street' %}
Hello world.
{% else %}
Apocalypse
{% endifequal %}