I posted this question earlier but it was then linked to a similar question which don't provide the required solution and was then closed for answering.
So I have created a Flask Application that tracks the movement of products from one location to another while I make movements via the Flask App the form doesn't get validated I tried adding {{ form.hidden_tag() }} and {{ form.csrf_token }} to the html file that takes input from the user.
If I run this application from the terminal on my command line the form is validated and gets added to the database but if I run the flask app and submit the form in the browser it doesn't.
here is my code for the same
class MovementForm(FlaskForm):
to_location = SelectField('To Location', coerce=int)
from_location = SelectField('From Location', coerce=int)
product = SelectField('Product')
quantity = IntegerField('Quantity')
add_movement = SubmitField('Add Movement')
#app.route('/movements',methods=["GET","POST"])
def add_movements():
form = MovementForm()
form.to_location.choices = [(location.id, location.location_name) for location in Location.query.all()]
form.from_location.choices = [(location.id, location.location_name) for location in Location.query.all()]
form.product.choices = [(product.id, product.product_name) for product in Product.query.all()]
form.from_location.choices.insert(0, (0, 'None'))
if form.validate_on_submit():
new_movement = Movement(to_location_id=form.to_location.data, from_location_id=form.from_location.data, product_id=form.product.data, quantity=form.quantity.data)
db.session.add(new_movement)
db.session.commit()
flash('Product has been moved!', 'success')
return redirect(url_for('add_movements'))
return render_template('add_movements.html', form=form)
Here is my html file
<form action="/movements" method="post">
{{ form.hidden_tag() }}
{{ form.csrf_token }}
<div class="row">
<div class="form-group col">
{{ form.from_location.label(class="form-control-label") }}
{{ form.from_location(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.to_location.label(class="form-control-label") }}
{{ form.to_location(class="form-control form-control-lg") }}
</div>
</div>
<div class="row">
<div class="form-group col">
{{ form.product.label(class="form-control-label") }}
{{ form.product(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.quantity.label(class="form-control-label") }}
{{ form.quantity(class="form-control form-control-lg") }}
</div>
</div>
<div class="form-group">
{{ form.add_movement(class="btn btn-outline-info") }}
</div>
</form>
What's wrong here?
Try to remove to change in the HTML form the form's action.
<form action="" method="post">
{{ form.hidden_tag() }}
{{ form.csrf_token }}
<div class="row">
<div class="form-group col">
{{ form.from_location.label(class="form-control-label") }}
{{ form.from_location(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.to_location.label(class="form-control-label") }}
{{ form.to_location(class="form-control form-control-lg") }}
</div>
</div>
<div class="row">
<div class="form-group col">
{{ form.product.label(class="form-control-label") }}
{{ form.product(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.quantity.label(class="form-control-label") }}
{{ form.quantity(class="form-control form-control-lg") }}
</div>
</div>
<div class="form-group">
{{ form.add_movement(class="btn btn-outline-info") }}
</div>
</form>
Does this solve the issue?
Also What I suggest you is to add the Flash message into the HTML, because I see that once the Form is submitted it returns back to the 'add_movements' function. Therefore add this:
<div>
{% for msg in get_flashed_messages%}
<h1>{{msg}}</h1>
{% endfor %}
</div>
<form action="" method="post">
{{ form.hidden_tag() }}
{{ form.csrf_token }}
<div class="row">
<div class="form-group col">
{{ form.from_location.label(class="form-control-label") }}
{{ form.from_location(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.to_location.label(class="form-control-label") }}
{{ form.to_location(class="form-control form-control-lg") }}
</div>
</div>
<div class="row">
<div class="form-group col">
{{ form.product.label(class="form-control-label") }}
{{ form.product(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.quantity.label(class="form-control-label") }}
{{ form.quantity(class="form-control form-control-lg") }}
</div>
</div>
<div class="form-group">
{{ form.add_movement(class="btn btn-outline-info") }}
</div>
#EDIT
I noticed that something is missing in the product field once coerce in missing:
class MovementForm(FlaskForm):
to_location = SelectField('To Location', coerce=int)
from_location = SelectField('From Location', coerce=int)
product = SelectField('Product', coerce=int)
quantity = IntegerField('Quantity')
add_movement = SubmitField('Add Movement')
EDIT #2
In case you run in this kind of issues (which happens all the time) I suggest you to add a print statements and a If/Else clause as well. This will dramatically help you where the issue is ( The issue on your type of problem you posted is that you 'don't see it') and will give you 'eyes.'
For example this is what I would have done:
#app.route('/movements',methods=["GET","POST"])
def add_movements():
form = MovementForm()
form.to_location.choices = [(location.id, location.location_name) for
location in Location.query.all()]
form.from_location.choices = [(location.id, location.location_name)
for location in Location.query.all()]
form.product.choices = [(product.id, product.product_name) for product
in Product.query.all()]
form.from_location.choices.insert(0, (0, 'None'))
if form.validate_on_submit():
print('Form Ok') #if you see the 'Form ok' to see if is validated
new_movement = Movement(to_location_id=form.to_location.data,
from_location_id=form.from_location.data,
product_id=form.product.data, quantity=form.quantity.data)
db.session.add(new_movement)
db.session.commit()
flash('Product has been moved!', 'success')
return redirect(url_for('add_movements'))
else:
print('Form Not Ok') #If you see this printed then you see that
#is not validated
return render_template('add_movements.html', form=form)
Related
I made a edit product function where you can change stock, name, discount of the product but i cannot seem to retrieve the details and 'GET' method it in the form so that user does not have to retype the details they don't wish to change
I'm using flask forms and python jinja, to do this
This is my routes.py
#app.route('/updateProduct/<int:id>', methods=['GET','POST]'])
def update_product(id):
form = UpdateProduct()
product = AddProduct.query.get_or_404(id)
if request.method == "POST" and form.validate_on_submit():
product.name = form.name.data
product.price = form.price.data
product.stock = form.stock.data
product.discount = form.discount.data
product.desc = form.description.data
try:
db.session.add(product)
db.session.commit()
flash(f'Your product has been successfully updated!')
print("a product has been updated")
return redirect(url_for('retrieve_products', id=product.id))
except:
print("error updating product")
return redirect(url_for('retrieve_products', id=product.id))
form.name.data = product.name
form.price.data = product.price
form.stock.data = product.stock
form.discount.data = product.discount
form.description.data = product.desc
return render_template('retrieveProducts.html', form=form)
this is the edit form modal in my retrieveproducts.html
<td style="color:black">
<button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#myModal2_{{ product.id }}">
Edit
</button>
<div class="modal" id="myModal2_{{product.id}}">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" style="color:black">Update Inventory</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal">X</button>
</div>
<div class="modal-body">
<form action="{{ url_for('update_product',id=product.id) }}" method="POST" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.name.label(class="form-control-label") }}
{{ form.name(class="form-control") }}
</div>
<div class="form-group">
{{ form.price.label(class="form-control-label") }}
{{ form.price(class="form-control") }}
</div>
<div class="form-group">
{{ form.discount.label(class="form-control-label") }}
{{ form.discount(class="form-control") }}
</div>
<div class="form-group">
{{ form.stock.label(class="form-control-label") }}
{{ form.stock(class="form-control") }}
</div>
<div class="form-group">
{{ form.description.label(class="form-control-label") }}
{{ form.description(class="form-control") }}
</div>
<div class="modal-footer">
{{ form.edit_submit(class="btn btn-primary") }}
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>
</td>
Try this:
#app.route('/updateProduct/<int:id>', methods=['GET','POST']) # Remove the extra bracket
In your route, you did not passed product variable:
<form action="{{ url_for('update_product',id=product.id) }}" method="POST" enctype="multipart/form-data">
This should create an error when you submit the form as product.id does not exist.
[Added]
return render_template('retrieveProducts.html', form=form, product=product)
Although I prefer to pass id variable since the route already has it.
I think you don't have to write
db.session.add(product)
db.session.commit()
because adding means you are creating a new record in your database, so just remove the part: ' db.session.add(product) ' and
keep only: ' db.session.commit() '
commit will update the existing content.
I hope this would help you, just try it a once and notify here.
Pass the product in your render template method as follows
return render_template('retrieveProducts.html', form=form, product=product)
Pass a value property in forms in order to get the current product details i.e
<div class="form-group">
{{ form.stock.label(class="form-control-label") }}
{{ form.stock(class="form-control", value=product.stock) }}
</div>
I'm trying to render an html form and pass in a table row with sqlalchemy. So then the form will show up with all it's input fields filled with the row data, with the purpose of editing and sending it back to the db. But somehow the form is displaying only two input fields, both of type text. Integer fields and radio fields are not showing the row's each corresponding value, although the values exist and are not none.
Here's the route:
#app.route('/editar/<string:id>')
def hotel_edit(id):
form = HotelForm()
viaje = arribos.query.get(id)
return render_template('edit_hotel.html', form=form, viaje=viaje)
Here's the html file displaying the wtform object + trying to get the object "viaje" to show the values with no luck:
{% block body %}
<div id="main_form">
<form action="/" method="post" id="ingresos">
{{ form.hidden_tag() }}
<fieldset>
<div class="checks" id="inout">
{{ form.check.label }}
{{ form.check(value=viaje.check) }}
</div>
<div class="horafecha">
{{ form.fecha.label }}
{{ form.fecha(value=viaje.fecha) }}
{{ form.hora.label }}
{{ form.hora(value=viaje.hora) }}
</div>
<div class="textbox">
{{ form.vuelo.label(class="inputtext") }}
{{ form.vuelo(class="inputtext", value=viaje.vuelo) }}
{{ form.habitacion.label(class="inputtext") }}
{{ form.habitacion(class="inputtext", value=viaje.habitacion) }}
{{ form.huespedes.label(class="inputtext") }}
{{ form.huespedes(class="inputtext", value=viaje.huespedes) }}
{{ form.valijas.label(class="inputtext") }}
{{ form.valijas(class="inputtext", value=viaje.valijas) }}
</div>
<div class="checks" id="puerto">
{{ form.puerto.label(class="puertos") }}
{{ form.puerto(class="puertos", value=viaje.puerto) }}
</div>
<div class="buttons">
{{ form.enviar }}
</div>
</fieldset>
</form>
</div>
{% endblock %}
And here's the form (not styled yet):
form
As you can see, most of the input fields are missing the value. Does anyone know how to fix this?
Also: I can show you the form.py file that has the class definition for the entire form, if that helps.
You can populate the form before it's sent to the jinja template from within your route. It would look something like this:
#app.route('/editar/<string:id>')
def hotel_edit(id):
form = HotelForm()
viaje = arribos.query.get(id)
form.check.data = viaje.check
form.fecha.data = viaje.fecha
form.hora.data = viaje.hora
...
return render_template('edit_hotel.html', form=form)
You can then just refer to the form field without passing the value arg.
{% block body %}
<div id="main_form">
<form action="/" method="post" id="ingresos">
{{ form.hidden_tag() }}
<fieldset>
<div class="checks" id="inout">
{{ form.check.label }}
{{ form.check() }}
</div>
<div class="horafecha">
{{ form.fecha.label }}
{{ form.fecha() }}
{{ form.hora.label }}
{{ form.hora() }}
</div>
<div class="textbox">
{{ form.vuelo.label(class="inputtext") }}
{{ form.vuelo(class="inputtext") }}
{{ form.habitacion.label(class="inputtext") }}
{{ form.habitacion(class="inputtext") }}
{{ form.huespedes.label(class="inputtext") }}
{{ form.huespedes(class="inputtext") }}
{{ form.valijas.label(class="inputtext") }}
{{ form.valijas(class="inputtext") }}
</div>
<div class="checks" id="puerto">
{{ form.puerto.label(class="puertos") }}
{{ form.puerto(class="puertos") }}
</div>
<div class="buttons">
{{ form.enviar }}
</div>
</fieldset>
</form>
</div>
{% endblock %}
While "DataRequired" and "NumberRange" produce a pop-up error message, "EqualTo" (and my own custom "MoreThan") do not. How can I get them to also produce a pop-up message?
####################################################################
My form has three fields. "min_nFeatures" has to be lower than "max_nFeatures", so I changed the code of the "EqualTo" validator to "MoreThan" (as advised in Code a validator for a WTForms form which compares the inputs from two fields). The validator is working: if the user enters a larger value for "min_nFeatures", it does not go through (it returns to the same page). However, there is no pop-up message as with the other built-in validators (for example, if the user does not enter anything, there's a pop-up "Please fill out this field"). I would like the same behavior for the custom validator.
My code:
class MoreThan(object):
def __init__(self, fieldname, message=None):
self.fieldname = fieldname
self.message = message
def __call__(self, form, field):
try:
other = form[self.fieldname]
except KeyError:
raise ValidationError(field.gettext("Invalid field name '%s'.") % self.fieldname)
if field.data <= other.data:
d = {
'other_label': hasattr(other, 'label') and other.label.text or self.fieldname,
'other_name': self.fieldname
}
message = self.message
if message is None:
message = field.gettext(
'The maximal number of expressed genes has to be larger than the minimal number of expressed genes')
raise ValidationError(message)
class vln_plot_form(FlaskForm):
min_nFeatures = IntegerField('* Minimal number of expressed genes:', validators=[DataRequired()])
max_nFeatures = IntegerField('* Maximal number of expressed genes:',
validators=[DataRequired(), MoreThan('min_nFeatures')])
max_mtpercent = IntegerField('Maximal percent of mitochondrial gene expression:', validators=[NumberRange(1, 100)])
submit = SubmitField('Submit')
view:
#app.route('/vln', methods=['POST', 'GET'])
def violin_plots():
...
form = vln_plot_form()
if request.method == 'POST':
if form.validate_on_submit():
...
return redirect(url_for('next_page'))
return render_template('violin_plots.html', form=form)
I read Message not flashing on some WTForm validation methods but could not apply it to my case.
########################################################################
edit:
Here's my HTML code:
{% extends 'base.html' %}
{% block head %}
<title>HELLO</title>
{% endblock %}
{% block body %}
<center><h1>Run!</h1></center>
<h2>Step 2/3</h2>
<figure>
<img src={{ vln_plot_file }} align="middle" alt="vln_plot" style="width:70%">
</figure>
<form method="POST" action="" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<div class="form-horizontal">
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.min_nFeatures.label }}</label>
{{ form.min_nFeatures }}
</div>
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.max_nFeatures.label }}</label>
{{ form.max_nFeatures }}
</div>
{% if with_mt %}
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.max_mtpercent.label }}</label>
{{ form.max_mtpercent }}
</div>
{% endif %}
<div class="form-group">
{{ form.csrf_token() }}
{{ form.submit(class="btn btn-primary")}}
</div>
</div>
{% if form.errors %}
{{ form.errors }}
{% endif %}
</form>
{% endblock %}
Since I added "{{ form.errors }}" at the end of the HTML, I do see the correct form.errors at the bottom of the webpage, but this is of course a very ugly way to display the errors...
This should do the trick:
<form method="POST" action="" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<div class="form-horizontal">
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.min_nFeatures.label }}</label>
{{ form.min_nFeatures }}
{% for error in form.min_nFeatures.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</div>
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.max_nFeatures.label }}</label>
{{ form.max_nFeatures }}
{% for error in form.max_nFeatures.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</div>
{% if with_mt %}
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.max_mtpercent.label }}</label>
{{ form.max_mtpercent }}
{% for error in form.max_mtpercent.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</div>
{% endif %}
<div class="form-group">
{{ form.csrf_token() }}
{{ form.submit(class="btn btn-primary")}}
</div>
</div>
</form
Note how I manage the display of errors for each of the fields individually.
I am trying to create a employee using a form. I want that after pressing the submit buttom data saves to employee list table and the page redirect to employee list table also. When I see the error log it shows Method Not Allowed (POST) . I think my code is fine but somehow it is not working.
employee_add_form.html:
{% extends 'base.html' %}
{% block content %}
{% load static %}
<link rel="stylesheet" href="{% static 'employee/css/master.css' %}">
{% load bootstrap4 %}
<div class="">
<form class="form" action="{% url 'employee:employee-list' %}" method="post" id="employee_add_form">
{% csrf_token %}
<!-- {% bootstrap_css %}-->
{% bootstrap_javascript jquery='full' %}
{{ form.media }}
{{ form.non_field_errors }}
<div class="container">
<label for=""><b>Personal Info</b></label>
<div class="border">
<div class="form-row">
<div class="col">
{{ form.first_name.errors }}
<label for="">First Name</label>
{{ form.first_name}}
</div>
<div class="col">
{{ form.last_name.errors }}
<label for="">Last Name</label>
{{ form.last_name}}
</div>
<div class="col">
{{ form.photo_id.errors }}
<label for="">Photo ID</label>
{{ form.photo_id }}
</div>
</div>
<div class="form-row inline">
<div class="col-4">
{{ form.gender.errors }}
<label for="">Gender</label>
{{ form.gender }}
</div>
<div class="col-4">
{{ form.blood_group.errors }}
<label for="">Blood Group</label>
{{ form.blood_group }}
</div>
<div class="col-4">
{{ form.religion.errors }}
<label for="">Religion</label>
{{ form.religion }}
</div>
</div>
<div class="form-row">
<div class="col">
{{ form.birth_date.errors }}
<label for="">Date of Birth</label>
{{ form.birth_date }}
</div>
</div>
</div>
</div>
<div class="container">
<label for=""><b>Contact Info</b></label>
<div class="border">
<div class="form-row">
<div class="col">
{{ form.email.errors }}
<label for="">Email</label>
{{ form.email }}
</div>
<div class="col">
{{ form.phone_number.errors }}
<label for="">Phone Number</label>
{{ form.phone_number }}
</div>
<div class="col">
{{ form.address.errors }}
<label for="">Address</label>
{{ form.address }}
</div>
</div>
</div>
</div>
<div class="container">
<label for=""><b>Work Info</b></label>
<div class="border">
<div class="form-row">
<div class="col">
{{ form.e_id.errors }}
<label for="">Employee ID</label>
{{ form.e_id }}
</div>
<div class="col">
{{ form.designation.errors }}
<label for="">Designation</label>
{{ form.designation }}
</div>
<div class="col">
{{ form.department.errors }}
<label for="">Department</label>
{{ form.department }}
</div>
</div>
<div class="form-row">
<div class="col">
{{ form.join_date.errors }}
<label for="">Joining Date</label>
{{ form.join_date }}
</div>
</div>
</div>
</div>
<div class="container">
<label for=""><b>Attachments</b></label>
<div class="border">
<div class="form-group">
<div class="col">
{{ form.cv.errors }}
<label for="">CV</label>
{{ form.cv }}
</div>
<div class="col">
{{ form.document.errors }}
<label for="">Documents</label>
{{ form.document }}
</div>
<div class="col">
{{ form.photo.errors }}
<label for="">Image</label>
{{ form.photo }}
</div>
</div>
</div>
</div>
<div class="container">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
{% endblock %}
views.py:
class EmployeeAddView(CreateView):
"""
Created new employee
"""
template_name = 'employee/employee_add_form.html'
form_class = EmployeeAddModelForm
# queryset = Employee.objects.all()
model = Employee
def form_valid(self, form):
print(form.cleaned_data)
return super().form_valid(form)
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('employee:employee-list')
return render(request, self.template_name, {'form': form})
urls.py:
from django.urls import path
from django.urls import reverse
from . views import (
EmployeeListView,
EmployeeAddView,
EmployeeDetailView,
EmployeeUpdateView,
EmployeeDeleteView,
)
app_name = 'employee'
urlpatterns = [
path('employee-list/', EmployeeListView.as_view(), name='employee-list'),
path('employee-add/', EmployeeAddView.as_view(), name='employee-add'),
path('employee-list/<int:id>/', EmployeeDetailView.as_view(), name='employee-detail'),
path('employee-list/<int:id>/update/', EmployeeUpdateView.as_view(), name='employee-update'),
path('employee-list/<int:id>/delete/', EmployeeDeleteView.as_view(), name='employee-delete'),
]
forms.py:
from django import forms
from core.models import Employee
from bootstrap_datepicker_plus import DatePickerInput
class EmployeeAddModelForm(forms.ModelForm):
use_required_attribute = False
class Meta:
model = Employee
fields = [
'e_id',
'first_name',
'last_name',
'gender',
'religion',
'blood_group',
'birth_date',
'photo_id',
'designation',
#'employee_type',
'join_date',
'address',
'phone_number',
'email',
#'supervisor',
'bank_account_no',
'department',
#'salary_type',
'cv',
'document',
'photo',
]
widgets = {
'birth_date': DatePickerInput(),
'join_date': DatePickerInput(),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Edit label:
self.fields['e_id'].label = 'Employee ID'
self.fields['cv'].label = 'CV'
# Remove help suggestion
for fieldname in ['e_id',
'first_name',
'last_name',
'gender',
'religion',
'blood_group',
'birth_date',
'photo_id',
'designation',
#'employee_type',
'join_date',
'address',
'phone_number',
'email',
#supervisor',
'bank_account_no',
'department',
#'salary_type',
'cv',
'document',
'photo']:
self.fields[fieldname].help_text = None
Your form is POST-ing to wrong URL
<form class="form" action="{% url 'employee:employee-list' %}" method="post" id="employee_add_form">
instead should be
<form class="form" action="{% url 'employee:employee-add' %}" method="post" id="employee_add_form">
If you are using class based view than you can do this.
class EmployeeAddView(CreateView):
template_name = 'employee/employee_add_form.html'
form_class = EmployeeAddModelForm
queryset = Employee.objects.all()
success_url = '/employee-list'
def form_valid(self, form):
print(form.cleaned_data)
return super().form_valid(form)
Change method="post" to method="POST" it should work. I had a similar problem with CBV. This worked for me.
there.
I defined a class called LoginForm:
class LoginForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Length(5, 64), Email()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember me')
submit = SubmitField('Log In')
Then I render it in the templates login.html:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
It looks like above:
And I think it is a little bit ugly. So, I render the fields in the normal way:
<form action="" method="POST" role="form" class="form">
{{ form.hidden_tag() }} {{ wtf.form_errors(form, hiddens="only") }}
<div class="form-group required">
<label class="control-label" for="email">Email</label>
{{ form.email(class="form-control",id="email",required="required",type="text",value="",placeholder="Enter email") }}
</div>
<div class="form-group required">
<label class="control-label" for="password">Password</label>
{{ form.password(class="form-control",id="password",required="required",type="password",value="",placeholder="Enter email") }}
</div>
<div class="checkbox">
<label>
<input id="remember_me" name="remember_me" type="checkbox" value="y"> Remember me
</label>
</div>
{{ form.submit(class="btn btn-success btn-block") }}
Register
</form>
It agrees with me now. But I met a problem: When I click the green login button, it does not validate the data(like the format of a email address). How should I solve this problem?
First I thought that it is not validating. Thank #BurhanKhalid for reminding me.
It's just not showing the errors. I changed the code and it works.
{% if form.email.errors %}
<div class="form-group required has-error">
{{ form.email(class="form-control",id="email",required='required',type="text",value="",placeholder="Enter email") }}
{% for error in form.email.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
{% else %}
<div class="form-group required">
{{ form.email(class="form-control",id="email",required='required',type="text",value="",placeholder="Enter email") }}
{% endif %}
</div>