My TextField forms are displaying fine in the html page, but not the DecimalFields. The DecimalFields don't display at all.
My forms.py:
from flask.ext.wtf import Form
from wtforms import TextField, validators, IntegerField, DateField, BooleanField, DecimalField
class EnterPart(Form):
Description = TextField(label='label', description="description", validators=[validators.required()])
VendorCost = DecimalField(label='label',description="cost")
My application.py:
from flask import Flask, render_template, request, redirect, url_for
def index():
form = EnterPart(request.form)
return render_template('index.html', form=form)
My index.html:
{% extends "base.html" %} {% import 'macros.html' as macros %}
{% block content %}
{{ form.hidden_tag() }}
{{ macros.render_field(form.Description, placeholder='Description', type='dbSerial', label_visible=false) }}
{{ macros.render_field(form.VendorCost, placeholder='Category', type='dbSerial', label_visible=false) }}
{% endblock %}
I've been building from the tutorial here:
http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
Thanks in advance.
Macros.html didn't have an option for dealing with DecimalField. By adding a rendering option for DecimalField, it now displays correctly.
I changed a block in macros.html from:
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
{% if (field.type != 'HiddenField' or field.type !='CSRFTokenField') and label_visible %}
<label for="{{ field.id }}" class="control-label">{{ field.label }}</label>
{% endif %}
{% if field.type == 'TextField' %}
{{ field(class_='form-control', **kwargs) }}
{% endif %}
{% if field.errors %}
{% for e in field.errors %}
<p class="help-block">{{ e }}</p>
{% endfor %}
{% endif %}
</div>
to:
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
{% if (field.type != 'HiddenField' or field.type !='CSRFTokenField') and label_visible %}
<label for="{{ field.id }}" class="control-label">{{ field.label }}</label>
{% endif %}
{% if field.type == 'TextField' %}
{{ field(class_='form-control', **kwargs) }}
{% endif %}
{% if field.type == 'DecimalField' %}
{{ field(class_='form-control', **kwargs) }}
{% endif %}
{% if field.errors %}
{% for e in field.errors %}
<p class="help-block">{{ e }}</p>
{% endfor %}
{% endif %}
</div>
Related
The form does not show any errors when i try to submit it, it just reload the sign up page even though there are errors in my input, i used an if statement to see there are errors and the for loop to display each error but they do not seem to be working. what am i doing wrong and how can i solve it?
main.py
from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms.fields import StringField, EmailField, PasswordField, SubmitField, TextAreaField, BooleanField
from wtforms.validators import Length, DataRequired, Email, EqualTo, Optional
class SignUp(FlaskForm):
username = StringField(label="username", validators=[Length(min=5, max=20), DataRequired(message="enter a name")])
first_name = StringField(label="first name", validators=[Length(min=5, max=20), DataRequired()])
last_name = StringField(label="last name", validators=[Length(min=5, max=20), DataRequired()])
email = EmailField(label="email", validators=[DataRequired(), Length(min=6)])
password = PasswordField(label="password", validators=[Length(min=8, max=40), DataRequired()])
confirm_password = PasswordField(label="confirm password", validators=[EqualTo(password), DataRequired()])
message = TextAreaField(label="message", validators=[Length(min=10, max=120), Optional()])
agree = BooleanField(label="I agree to the terms and conditions")
submit = SubmitField(label="Sign Up")
app = Flask(__name__)
app.config["SECRET_KEY"] = "uhr78hv98n4n8y7b6em98x8794c87x3m98xtmmsce9n8ce"
#app.route("/")
#app.route("/home")
def home():
return render_template("index.html")
#app.route("/signup", methods=["POST", "GET"])
#app.route("/register", methods=["POST", "GET"])
def sign_up():
form = SignUp()
if request.method == "POST":
if form.validate_on_submit():
pass
return render_template("signup.html", form=form)
if __name__ == "__main__":
app.run(debug=True)
signup.html
{% extends "base.html" %} {% block head %}
<title>Sign UP</title>
{% endblock head %} {% block body %}
<h1>Sign Up</h1>
<form method="POST" action="{{ url_for('sign_up') }}" novalidate>
{{ form.csrf_token }}
<div class="field">
{{ form.username.label }} {{ form.username }} {% if form.username.errors %}
{% for error in form.username.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.first_name.label }} {{ form.first_name }} {% if
form.first_name.errors %} {% for error in form.first_name.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.last_name.label }} {{ form.last_name }} {% if form.last_name.errors
%} {% for error in form.last_name.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.email.label }} {{ form.email }} {% if form.email.errors %} {% for
error in form.email.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.password.label }} {{ form.password }} {% if form.password.errors %}
{% for error in form.password.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.confirm_password.label }} {{ form.confirm_password }} {% if
form.confirm_password.errors %} {% for error in form.confirm_password.error
%}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.message.label }} {{ form.message }} {% if form.message.errors %} {%
for error in form.message.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
{{ form.agree }} <br />
{{ form.submit }}
</form>
{% endblock body %}
I have been working on a website for the past while using flask, python and bootstrap. I added footer to my website and I would like a "contact me" form in the footer. Below is my current code for creating a contact form and displaying this form.
class ContactForm(FlaskForm):
email = StringField("", validators=[DataRequired(), Email()])
content = TextAreaField("", validators=[DataRequired(), length(min=2, max=500)])
submit = SubmitField("Submit")
<form method="POST" action="">
<div class="form-group">
{{ form.email.label(class="form-control-label") }}
{% if form.email.errors %}
{{ form.email(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.email.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.email(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.content.label(class="form-control-label") }}
{% if form.content.errors %}
{{ form.content(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.content.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.content(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
I created this footer in my "layout.html" file which is the base file that all other html documents extend from so that all pages will have this same footer.
The issue is that then I need to create and instance of this form object on every page of my application and handle the validate_on_submit on every page. (Sample code below)
#app.route("/random_page", methods=["GET", "POST"])
def random_page():
form = ContactForm()
if form.validate_on_submit():
# code to send the email goes here
return render_template("random_page")
I am looking for an easier way to do this so that I don't need to repeat code on every page and so that It can be considerably simpler. I am not very experienced with flask and would highly appreciate the help.
Use the #app.context_processor decorator, documentation to inject an instance of your contact form into the template context for all templates. For example:
#app.context_processor
def inject():
return dict(
contact_form=ContactForm(),
)
Then re-write the form's HTML to use the contact_form template variable, also adding in an appropriate action route.
<form method="POST" action="{{url_for('contact')}}">
<div class="form-group">
{{ contact_form.email.label(class="form-control-label") }}
{% if contact_form.email.errors %}
{{ contact_form.email(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.email.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ contact_form.email(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ contact_form.content.label(class="form-control-label") }}
{% if contact_form.content.errors %}
{{ contact_form.content(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in contact_form.content.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ contact_form.content(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ contact_form.submit(class="btn btn-outline-info") }}
</div>
</form>
Then add a route to solely handle this form's postback:
#app.route("/contact", methods=["POST"])
def contact():
form = ContactForm()
if form.validate_on_submit():
# code to send the email goes here
# blah blah
I have designed a form to update a task. The form will get the details of the task into the update form and while submitting that form the form.validate_on_submit does not work and redirects again to the same form with the previous values. Here are my routes and template code. I have used {{ form.csrf_token }}. But similar logic works with the newTask route.
Update Route
#main.route('/update/<int:id>',methods=['POST','GET'])
#login_required
def update(id):
if form.validate_on_submit():
t.task_name = form.task_name.data
t.assignee = form.assignee.data
t.deal_size = form.deal_size.data
t.lead_status = form.lead_status.data
t.stage = form.stage.data
t.priority = form.priority.data
t.submission_date = form.date.data
db.session.add(t)
db.session.commit()
return redirect('/')
form = NewTaskForm()
t = Tasks.query.get_or_404(id)
return render_template("update.html",form = form , t = t)
update.html
<form method="POST" action="/update/{{ t.id }}">
{{ form.csrf_token }}
<div class="form-group">
{{ form.task_name.label }}{{ form.task_name(class='form-control',value = t.task_name ) }}
{% if form.task_name.errors %}
{% for error in form.task_name.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{ form.assignee.label }}{{ form.assignee(class='form-control',value = t.assignee) }}
{% if form.assignee.errors %}
{% for error in form.assignee.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{ form.deal_size.label }}{{ form.deal_size(class='form-control',value = t.deal_size) }}
{% if form.deal_size.errors %}
{% for error in form.deal_size.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{ form.lead_status.label }}{{ form.lead_status(class='form-control',value = t.lead_status) }}
{% if form.lead_status.errors %}
{% for error in form.lead_status.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-check padding-none">
{{ form.stage.label(class='form-check-label') }}{{ form.stage(class='form-check-input customRadio',value = t.stage.data) }}
{% if form.stage.errors %}
{% for error in form.stage.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{ form.date.label }}{{ form.date(class='form-control',value = t.submission_date.date()) }}
{% if form.date.errors %}
{% for error in form.date.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
{{ form.submit(class="btn btn-outline-primary btn-block") }}
</form>
newTask route
#main.route('/new-task',methods=['POST','GET'])
#login_required
def newTask():
form = NewTaskForm()
if form.validate_on_submit():
t = Tasks()
t.task_name = form.task_name.data
t.assignee = form.assignee.data
t.deal_size = form.deal_size.data
t.lead_status = form.lead_status.data
t.stage = form.stage.data
t.priority = form.priority.data
t.submission_date = form.date.data
db.session.add(t)
db.session.commit()
return redirect('/')
return render_template("newtask.html",form = form)
If you want to redirect the user to the new form use:
#main.route('/update/<int:id>',methods=['POST','GET'])
#login_required
def update(id):
if form.validate_on_submit():
# do something and then redirect
return redirect(url_for('confirm'))
return render_template("update.html",form = form , t = t)
Probably, you need to create a new function for the 'confirmation site' if you haven't done already.
You can look up the flask documentation if you want to have a better understanding of
url_for :
It accepts the name of the function as its first argument and any number of keyword arguments, each corresponding to a variable part of the URL rule. Unknown variable parts are appended to the URL as query parameters.
Here you can find a good explanation as well:
create-dynamic-urls-in-flask
when Making django board, I met the problem.
django version is 3.
I wanted form like this. but my code can't alert me "This field is required"
But widget tweaks form-control wasn't working.
which part is problem?
My code is like this
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block title %}Start a New Topic{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Boards</li>
<li class="breadcrumb-item">{{ board.name }}</li>
<li class="breadcrumb-item active">New topic</li>
{% endblock %}
{% block content %}
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text }}
</small>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-success">Post</button>
</form>
{% endblock %}
Try using bootstrap or django crispy forms in your form.
just change your code to blow with proper indent
{% load widget_tweaks %}
{% block title %}Start a New Topic{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Boards</li>
<li class="breadcrumb-item">{{ board.name }}</li>
<li class="breadcrumb-item active">New topic</li>
{% endblock %}
{% block content %}
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text }}
</small>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-success">Post</button>
</form>
{% endblock %}```
I am trying to use Crispy forms with Django-userena to make it look better but when ever I put the Crispy form tags in it duplicates the form,
My code is as followed:
{% extends 'userena/base_userena.html' %}
{% load i18n %}
{% load url from future %}
{% load crispy_forms_tags %}
{% block title %}{% trans "Signin" %}{% endblock %}
{% block content %}
<form action="" method="post" class="formholder">
{% csrf_token %}
{{ form|crispy }}
<fieldset>
<legend>{% trans "Signin" %}</legend>
{{ form.non_field_errors }}
{% for field in form %}
{{ field.errors }}
{% comment %} Displaying checkboxes differently {% endcomment %}
{% if field.name == 'remember_me' %}
<p class="checkbox">
<label for="id_{{ field.name }}">{{ field }} {{ field.label }}</label>
</p>
{% else %}
<p>
{{ field.label_tag }}
{{ field }}
</p>
{% endif %}
{% endfor %}
</fieldset>
<input type="submit" value="{% trans "Signin" %}" />
<p class="forgot-password">{% trans "Forgot your password?" %}</p>
{% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
</form>
{% endblock %}
Solution by OP.
The problem was that the, {{ form|crispy }} was actually creating the form in the form.py file all I had to do was remove all the other from tags and just keep the {{ form|crispy }}
Here is what it looks like:
{% extends 'userena/base_userena.html' %}
{% load i18n %}
{% load url from future %}
{% block title %}{% trans "Signin" %}{% endblock %}
{% block content %}
{% load crispy_forms_tags %}
<form action="" method="post" class="formholder">
{% csrf_token %}
<fieldset>
<legend>{% trans "Signin" %}</legend>
{{ form|crispy }}
</fieldset>
<input type="submit" value="{% trans "Signin" %}" />
<p class="forgot-password">{% trans "Forgot your password?" %}</p>
{% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
</div>
</form>
{% endblock %}