
El objetivo no es enseñarte Flask, ni WTForms, ni Bootstrap. Sino juntar estas tres tecnologías que ya conoces para realizar un formulario vistoso. En el siguiente ejemplo te mostraré como hacer una validación de un campo con WTForms y mostrar su mensaje de error con los estilos de Bootstrap.
Necesito tres archivos básicos: un HTML, un Python con la estructura mínima de Flask y donde irá nuestro formulario de WTForms.
HTML
Dentro de templates creamos un archivo llamado formulario.html. Contendrá el siguiente código.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
<title>Enemigos</title>
</head>
<body>
<div class="container">
<form action="" method="post">
{{ form.csrf_token }}
<div class="form-group{%if form.nombre.errors %} has-error{% endif %}">
{{ form.nombre.label }}
{{ form.nombre(class='form-control', value='') }}
{% for error in form.nombre.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
<input type="submit" class="btn btn-success" value="Añadir">
</form>
</div>
</body>
</html>
Nos aseguramos que en static tenemos css/bootstrap.min.css.
Flask
En un archivo llamado app.py, copiamos lo siguiente.
from flask import Flask, render_template, request
from forms import EnemigosForm
app = Flask(__name__)
app.secret_key = 'secreto'
@app.route("/", methods=('GET', 'POST'))
def index():
form = UserForm()
if form.validate_on_submit():
# Tu código si pasa las validaciones
pass
return render_template('enemigos.html', form=form)
if __name__ == "__main__":
app.run()
WTForms
Ahora toca el formulario con la validación campo obligatorio y el mensaje que saltará si no se cumple. Creamos forms.py. Y pegamos.
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired
class EnemigosForm(FlaskForm):
nombre = StringField('nombre', validators=[DataRequired('El nombre es obligatorio')])
Y se acabó.
EXTRA: Autogenerar todos los campos en el HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
<title>Enemigos</title>
</head>
<body>
<div class="container">
<form action="" method="post">
{% for campo in form %}
{% if campo.type != 'CSRFTokenField' %}
<div class="form-group{%if campo.errors %} has-error{% endif %}">
{{ campo.label }}
{% if campo.type in ('StringField', 'PasswordField') %}
{{ campo(class='form-control') }}
{% else %}
{{ campo() }}
{% endif %}
{% for error in campo.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ campo() }}
{% endif %}
{% endfor %}
<input type="submit" class="btn btn-success" value="Añadir">
</form>
</div>
</body>
</html>
{{ comments.length }} comentarios