Introducción a Flask: agregar una página de contacto

En el artículo anterior de esta miniserie, aprovechamos Matraz para crear un sitio web simple que contenga páginas de «Inicio» y «Acerca de» utilizando un flujo de trabajo generalizado que podemos aplicar a otras aplicaciones web basadas en Flask. En esta lección, demostraré cómo agregar una página de «Contacto» que permita a los usuarios enviarle mensajes.

El código utilizado en este artículo se puede encontrar en GitHub. Subtítulos, como Punto de control: 05_contact_formsignifica que puede cambiar a la rama denominada «05_contact_form» y revisar el código en ese punto del artículo.


Extensiones de matraz

Puede encontrar una lista completa de extensiones en el Registro de extensión de matraz.

Flask no viene con muchas funciones listas para usar, por lo que es fácil de aprender. No hay un asignador relacional de objetos para la interacción de la base de datos o interfaces de administración para agregar y actualizar contenido. Solo ofrece un pequeño conjunto de funciones, dos de las cuales ya hemos usado: url_for() y render_template().

En lugar de enviar con funcionalidad adicional, el modelo de extensión de Flask le permite agregar funcionalidad según sea necesario. Una extensión de Flask es un paquete que agrega una funcionalidad específica a su aplicación. Por ejemplo, Flask-SQLAlchemy agrega soporte de base de datos a su aplicación, mientras que Flask-Iniciar sesión agrega soporte de inicio/cierre de sesión. Puede encontrar una lista completa de extensiones en el Registro de extensión de matraz.

Para crear una página de contacto, usaremos Frasco-WTF para manejar y validar datos de formularios y Frasco de correo para enviarle por correo electrónico los datos del formulario.


Frasco-WTF

Frasco-WTF es una extensión que maneja y valida datos de formularios. ¿Que significa eso? Observa la siguiente figura:

Figura 1

  1. Un usuario emite una solicitud GET para una página web que contiene un formulario.
  2. El usuario rellena el formulario.
  3. El usuario hace clic en el botón «Enviar», enviándolo al servidor a través de una solicitud POST.
  4. El servidor valida la información.
  5. Si uno o más campos no se validan, la página web que contiene el formulario se vuelve a cargar con un útil mensaje de error que le pide al usuario que intente nuevamente.
  6. Si todos los campos son válidos, la información del formulario se usa en el siguiente paso de la canalización.

Una página de contacto tendrá campos para el nombre del usuario, correo electrónico, asunto y mensaje. En Flask, PUBLICAREMOS el formulario en una función dentro routes.py. Esta función se llama controlador de formulario. Ejecutaremos algunas comprobaciones de validación y, si alguna de las entradas no se supera, actualizaremos la página para mostrar un mensaje que describa el error. Una vez que pasen todas las comprobaciones de validación, utilizaremos los datos del formulario para el siguiente paso: enviarle el mensaje por correo electrónico a usted, el propietario del sitio web.

Las extensiones de Flask son herramientas sencillas y potentes que amplían la funcionalidad de su aplicación basada en Flask.

Así es como funciona el manejo y la validación de formularios. Ahora, ¿dónde definimos realmente la forma? Podríamos escribir HTML usando el <form> elemento y establezca su action atributo a un script de Python. La secuencia de comandos de Python reflejaría el formulario para capturar cada campo del formulario y validar los datos del campo del formulario. Sin embargo, si usamos esta estrategia, esencialmente definiríamos el formulario dos veces: una para el front-end y otra para el back-end.

Sería genial definir el formulario solo una vez: en el script de Python. Esto es exactamente lo que Flask-WTF nos permite hacer. Definiremos el formulario solo una vez en un script de Python y luego dejaremos que Flask-WTF genere el HTML del formulario por nosotros. El objetivo de todo esto es separar la presentación del contenido.

Basta de charla. Vamos a codificar.

Crear un formulario

Como primer paso, volvamos al entorno de desarrollo aislado que creamos la última vez.

1

2
$ cd flaskapp
3
$ . bin/activate

Ahora que hemos ingresado y activado nuestro entorno de desarrollo, podemos instalar Flask-WTF de manera segura:

1

2
$ pip install flask-wtf

Ahora definamos el formulario en un script de Python. Nosotros ya tenemos routes.py, que asigna direcciones URL a funciones. No lo desordenemos con código no relacionado. En su lugar, cree un nuevo archivo llamado forms.pyy colóquelo dentro del app/ carpeta.

app/formularios.py

1

2
from flask.ext.wtf import Form, TextField, TextAreaField, SubmitField
3

4
class ContactForm(Form):
5
  name = TextField("Name")
6
  email = TextField("Email")
7
  subject = TextField("Subject")
8
  message = TextAreaField("Message")
9
  submit = SubmitField("Send")

Acabamos de crear un formulario. ¿Qué hicimos? Primero, importamos algunas clases útiles de Flask-WTF: la base Form clase, un campo de texto, un campo de área de texto para la entrada de texto de varias líneas y un botón de envío. A continuación, creamos una nueva clase llamada ContactFormheredado de la base Form clase. Luego creamos cada campo que queremos ver en el formulario de contacto. en lugar de escribir <input type="text">Name</input> en un archivo HTML, escribes name = TextField("Name").

Usando el formulario

Ahora usemos nuestro formulario. Queremos que aparezca cuando un usuario visite la página de contacto. En términos de Flask, queremos que el formulario se muestre en una plantilla web y asigne una URL a esa plantilla web para que podamos visitarla en el navegador. Esto significa que necesitamos crear una nueva plantilla web y una nueva asignación de URL. Comencemos por crear una nueva asignación de URL.

Esta es una sección llena de acción y puede ser un poco confusa. Pero quédate conmigo y lo superaremos.

Como primer paso, abra routes.py e importe nuestro formulario recién creado agregando from forms import ContactForm al comienzo del guión.

app/rutas.py

1

2
from flask import Flask, render_template
3
from forms import ContactForm

Puede evitar un ataque CSRF asegurándose de que el envío del formulario se origine en su aplicación web.

A continuación, configure Flask-WTF para manejar una vulnerabilidad de seguridad conocida como falsificación de solicitud entre sitios (CSRF). En un mundo perfecto, su servidor solo procesaría formularios que pertenecen a su aplicación web. En otras palabras, su servidor solo manejaría y validaría los formularios que usted creó. Sin embargo, es posible que un atacante cree un formulario en su propio sitio web, lo complete con información maliciosa y lo envíe a su servidor. Si su servidor acepta esta información maliciosa, pueden ocurrir todo tipo de cosas malas a continuación.

Puede evitar un ataque CSRF asegurándose de que el envío del formulario se origine en su aplicación web. Una forma de hacer esto es mantener un token único oculto dentro de su HTML <form> etiqueta que los atacantes no pueden adivinar. Cuando el formulario se envía a su servidor, primero se verifica el token. Si el token no coincide, su servidor rechaza el envío del formulario y no toca los datos del formulario. Si el token coincide, el servidor continúa con el manejo y la validación del formulario.

Flask-WTF hace todo esto con una sola línea fácil. Simplemente configure Flask-WTF con una clave secreta, y Flask-WTF se encargará de generar y administrar tokens únicos para su formularios

app/rutas.py

1

2
from flask import Flask, render_template, request, flash
3
from forms import ContactForm
4

5
app = Flask(__name__) 
6

7
app.secret_key = 'development key'

Aquí, en la línea seis, establecí la clave secreta en ‘clave de desarrollo’. Siéntase libre de hacer el suyo más complejo, más largo y alfanumérico.

Ahora que importamos y configuramos nuestro formulario de contacto, podemos usarlo en un mapeo de URL en routes.py. Avancemos y creemos esa asignación de URL.

app/rutas.py

1

2
@app.route('/contact')
3
def contact():
4
  form = ContactForm()
5
  return render_template('contact.html', form=form)

Ahora, cuando alguien visita la URL /contactla función contact() ejecutará. En el interior contact()primero creamos una nueva instancia de nuestro formulario de contacto en la línea tres y la enviamos a una plantilla web llamada contact.html en la línea cuatro. Crearemos esta plantilla web en breve.

Sin embargo, todavía tenemos trabajo que hacer aquí. La Figura 1 mostró que si se envía una solicitud GET al servidor, la página web que contiene el formulario debe recuperarse y cargarse en el navegador. Si el servidor recibe una solicitud POST, una función debe capturar los datos del campo del formulario y verificar si es válido. En términos de Python, esta lógica se puede expresar en un if...else declaración. Hay una clase Flask para distinguir entre solicitudes GET y POST, así que comencemos importando esa clase al principio de routes.py y agrega el if...else lógica a la contact() función.

app/rutas.py

1

2
from flask import Flask, render_template, request
3
.
4
.
5
.
6
@app.route('/contact', methods=['GET', 'POST'])
7
def contact():
8
  form = ContactForm()
9

10
  if request.method == 'POST':
11
    return 'Form posted.'
12

13
  elif request.method == 'GET':
14
    return render_template('contact.html', form=form)

Ya importamos la clase Flask y render_template() en el artículo anterior, así que aquí importamos una clase Flask más llamada request. request determina si el método HTTP actual es GET o POST. El siguiente es el if...else lógica a la contact() función (líneas 9-13).

En el caso de una solicitud POST, se devolverá una cadena que indica que el formulario ha sido publicado.

Esta cadena es un marcador de posición temporal y la reemplazaremos con código real en el paso final de este artículo. De lo contrario, si la solicitud usa GET, devolvemos la plantilla web contact.html que contiene el formulario.

El siguiente paso es crear la plantilla web. contact.html y ponlo dentro del templates/ carpeta.

aplicación/plantillas/contacto.html

1

2
{% extends "layout.html" %}
3

4
{% block content %}
5
  <h2>Contact</h2>
6
  <form action="{{ url_for('contact') }}" method=post>
7
    {{ form.hidden_tag() }}
8

9
    {{ form.name.label }}
10
    {{ form.name }}
11

12
    {{ form.email.label }}
13
    {{ form.email }}
14

15
    {{ form.subject.label }}
16
    {{ form.subject }}
17

18
    {{ form.message.label }}
19
    {{ form.message }}
20

21
    {{ form.submit }}
22
  </form>
23
{% endblock %}

Al igual que con home.html y about.htmlla contact.html la plantilla se extiende layout.html y llena el bloque de ‘contenido’ con su propio texto. Primero especificamos dónde enviar los datos del formulario en el momento del envío configurando el <form> elementos action atribuir a la contact() función que creamos en routes.py (línea cinco). A continuación, dejamos que el motor de plantillas Jinja2 genere la mayor parte del formulario para nosotros (líneas 6-20). Comenzamos insertando una etiqueta oculta en la línea seis para protegernos contra las vulnerabilidades CSRF. Por último, agregamos cada etiqueta y campo del formulario.

Ya estamos listos para ver el resultado de todo nuestro trabajo. Simplemente escriba lo siguiente:

1

2
$ python routes.py

Luego ve a http://localhost:5000/contacto en su navegador web favorito.

Se ha cargado la página de contacto que contiene el formulario. Rellene los campos del formulario y haga clic en el botón «Enviar». Verás una página que se ve así:

¡Impresionante! El envío del formulario está funcionando.

Repasemos rápidamente todo lo que hicimos en esta sección:

  • Tecleamos la URL http://localhost:5000/contacto en la barra de direcciones del navegador.
  • La solicitud GET llega routes.pydonde la URL /contact se asigna a la función contact().
  • La función contact() se ejecuta, donde una variable llamada form que contiene una instancia utilizable del ContactForm la clase se envía a la plantilla web contact.html.
  • contact.html genera el HTML del formulario de contacto.
  • El HTML renderizado se envía de vuelta a routes.py.
  • routes.py envía el HTML de vuelta al navegador y vemos la página de contacto que contiene el formulario.
  • Rellenamos el formulario de contacto y lo enviamos haciendo clic en el botón «Enviar».
  • La solicitud POST llega routes.pydonde la URL /contact se asigna a la función contact().
  • La función contact() se ejecuta una vez más, esta vez siguiendo el if...else flujo de control para la solicitud HTTP POST.
  • La cuerda 'Form posted.' se envía de vuelta al navegador, dándonos la pantalla de arriba.

Punto de control: 05_contact_form

Esto es genial, pero el formulario de contacto se ve feo. Hagamos que se vea mejor agregando algo de CSS. Abrir main.css y agrega estos normas:

estático/css/main.css

1

2
/* Contact form */
3
form label {
4
  font-size: 1.2em;
5
  font-weight: bold;
6
  display: block;
7
  padding: 10px 0;
8
}
9

10
form input#name,
11
form input#email,
12
form input#subject {
13
  width: 400px;
14
  background-color: #fafafa;
15
  -webkit-border-radius: 3px;
16
     -moz-border-radius: 3px;
17
          border-radius: 3px;
18
  border: 1px solid #cccccc;
19
  padding: 5px;
20
  font-size: 1.1em;
21
}
22

23
form textarea#message {
24
  width: 500px;
25
  height: 100px;
26
  background-color: #fafafa;
27
  -webkit-border-radius: 3px;
28
     -moz-border-radius: 3px;
29
          border-radius: 3px;
30
  border: 1px solid #cccccc;
31
  margin-bottom: 10px;
32
  padding: 5px;
33
  font-size: 1.1em;
34
}
35

36
form input#submit {
37
  display: block;
38
  -webkit-border-radius: 3px; 
39
     -moz-border-radius: 3px;
40
          border-radius: 3px;
41
  border:1px solid #d8d8d8;
42
  padding: 10px; 
43
  font-weight:bold; 
44
  text-align: center; 
45
  color: #000000; 
46
  background-color: #f4f4f4;
47
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f4f4f4), color-stop(100%, #e5e5e5));
48
  background-image: -webkit-linear-gradient(top, #f4f4f4, #e5e5e5);
49
  background-image: -moz-linear-gradient(top, #f4f4f4, #e5e5e5);
50
  background-image: -ms-linear-gradient(top, #f4f4f4, #e5e5e5);
51
  background-image: -o-linear-gradient(top, #f4f4f4, #e5e5e5);
52
  background-image: linear-gradient(top, #f4f4f4, #e5e5e5);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#f4f4f4, endColorstr=#e5e5e5);
53
}
54

55
form input#submit:hover{
56
  cursor: pointer;
57
  border:1px solid #c1c1c1; 
58
  background-color: #dbdbdb;
59
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#dbdbdb), color-stop(100%, #cccccc));
60
  background-image: -webkit-linear-gradient(top, #dbdbdb, #cccccc);
61
  background-image: -moz-linear-gradient(top, #dbdbdb, #cccccc);
62
  background-image: -ms-linear-gradient(top, #dbdbdb, #cccccc);
63
  background-image: -o-linear-gradient(top, #dbdbdb, #cccccc);
64
  background-image: linear-gradient(top, #dbdbdb, #cccccc);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#dbdbdb, endColorstr=#cccccc);
65
}

Vuelva al navegador y actualice http://localhost:5000/contacto para ver el resultado del CSS.

Esto se ve mucho mejor. Pasemos a la validación de formularios.

Punto de control: 06_contact_styling

Validación de datos de formulario

Un usuario ahora puede visitar la URL /contact y rellene el formulario. Pero, ¿qué ocurre si el usuario no rellena correctamente el formulario? Necesitamos validar la entrada del usuario para que no cause problemas en pasos posteriores.

La validación de formularios se realiza mediante el uso de validadores de formularios. Afortunadamente, Flask-WTF viene con muchos validadores integrados útiles que podemos usar de inmediato. Pondremos estos validadores en el ContactForm definición de clase en forms.py.

El validador más básico es presenciaque simplemente garantiza que todos los campos del formulario se completen, así que comencemos aquí.

app/formularios.py

1

2
from flask.ext.wtf import Form, TextField, TextAreaField, SubmitField, validators, ValidationError
3

4
class ContactForm(Form):
5
  name = TextField("Name",  [validators.Required()])
6
  email = TextField("Email",  [validators.Required()])
7
  subject = TextField("Subject",  [validators.Required()])
8
  message = TextAreaField("Message",  [validators.Required()])
9
  submit = SubmitField("Send")

Empezamos importando validators y ValidationError de Flask-WTF. Esto nos da acceso a los validadores integrados de Flask-WTF. A continuación agregamos [validators.Required()] a cada campo del formulario para validar su presencia. Tenga en cuenta que este validador está dentro de una lista de Python, lo que significa que podemos agregar fácilmente más validadores a esta lista.

A continuación, exijamos direcciones de correo electrónico que coincidan con el patrón. user@example.com agregando el Correo electrónico validador al campo de correo electrónico.

app/formularios.py

1

2
from flask.ext.wtf import Form, TextField, TextAreaField, SubmitField, validators, ValidationError
3

4
class ContactForm(Form):
5
  name = TextField("Name",  [validators.Required()])
6
  email = TextField("Email",  [validators.Required(), validators.Email()])
7
  subject = TextField("Subject",  [validators.Required()])
8
  message = TextAreaField("Message",  [validators.Required()])
9
  submit = SubmitField("Send")

Eso lo hace para nuestras validaciones de formulario.

Punto de control: 07_form_validations

Mensajes de error intermitentes

Volviendo a la Figura 1, si falla alguna comprobación de validación, la página de contacto debería volver a cargarse con un mensaje de error para que el usuario pueda corregir el error e intentarlo de nuevo. Este mensaje de error solo debe aparecer cuando falla la validación y desaparecer cuando se corrige el error.

Nuestro siguiente paso es enviar este tipo de mensaje de error temporal al usuario cuando falla la validación. Flask lo hace realmente fácil usando su flash() función. Empecemos abriendo routes.py e importando Flask’s flash() función al principio del script.

app/rutas.py

1

2
from flask import Flask, render_template, request, flash

Después de que el formulario de contacto se publique en el servidor, cualquier falla de validación debería volver a cargar el formulario con un útil mensaje de error. De lo contrario, los datos de entrada se pueden utilizar para un procesamiento futuro. Una vez más, esta lógica se puede expresar en un if...else declaración. Agreguemos esto if...else lógica a la contact() función dentro de la if request.method == 'POST': bloquear.

app/rutas.py

1

2
@app.route('/contact', methods=['GET', 'POST'])
3
def contact():
4
  form = ContactForm()
5

6
  if request.method == 'POST':
7
    if form.validate() == False:
8
      flash('All fields are required.')
9
      return render_template('contact.html', form=form)
10
    else:
11
      return 'Form posted.'
12

13
  elif request.method == 'GET':
14
    return render_template('contact.html', form=form)

Si alguna verificación de validación falla, form.validate() estarán False. el mensaje de error All fields are required será enviado a contact.html. De lo contrario, veremos la cadena de marcador de posición temporal Form postedindicando que el formulario se ha enviado correctamente.

A continuación, modifiquemos contact.html para que pueda recibir y mostrar estos mensajes de error temporales. Ver el siguiente bloque:

1

2
{% for message in get_flashed_messages() %}
3
  <div class="flash">{{ message }}</div>
4
{% endfor %}

La función get_flashed_messages() extrae todos los mensajes flasheados y los devuelve. Luego, simplemente mostramos cada mensaje parpadeante usando un Jinja2 for círculo. Agregue este bloque de código a contact.html después <h2>Contact</h2> y ante el <form> etiqueta.

aplicación/plantillas/contacto.html

1

2
{% extends "layout.html" %}
3

4
{% block content %}
5
  <h2>Contact</h2>
6

7
  {% for message in get_flashed_messages() %}
8
    <div class="flash">{{ message }}</div>
9
  {% endfor %}
10
  
11
  <form action="{{ url_for('contact') }}" method=post>
12
    {{ form.hidden_tag() }}
13

14
    {{ form.name.label }}
15
    {{ form.name }}
16

17
    {{ form.email.label }}
18
    {{ form.email }}
19

20
    {{ form.subject.label }}
21
    {{ form.subject }}
22

23
    {{ form.message.label }}
24
    {{ form.message }}
25

26
    {{ form.submit }}
27
  </form>
28
{% endblock %}

Por último, agreguemos una regla CSS en main.css para que los mensajes de error parpadeantes se vean bonitos.

principal.css

1

2
/* Message flashing */
3
.flash {
4
  background-color: #FBB0B0;
5
  padding: 10px;
6
  width: 400px;
7
}

Abre tu navegador y visita http://localhost:5000/contacto. Deje todos los campos en blanco y haga clic en «Enviar» para probar si la validación del formulario y el mensaje de error funcionan.

¡Esto es dulce! Hemos enviado con éxito un mensaje de error a nuestro formulario de contacto si falla una verificación de validación.

Punto de control: 08_error_message_flashing

Pero no hemos terminado; en realidad podemos hacerlo un poco mejor. En lugar de tener un mensaje de error genérico para todas las comprobaciones de validación fallidas, sería mejor tener un mensaje de error específico para cada comprobación de validación fallida. Por ejemplo, si el usuario olvida completar el campo de asunto, un mensaje de error específico que dice Please enter a subject sería flasheado. Del mismo modo, si el usuario olvida ingresar su nombre, mostraremos un mensaje de error específico que dice Please enter your name. Podemos lograr esto con bastante facilidad, así que comencemos escribiendo nuestros mensajes de error específicos dentro de cada validador en forms.py.

app/formularios.py

1

2
from flask.ext.wtf import Form, TextField, TextAreaField, SubmitField, validators, ValidationError
3

4
class ContactForm(Form):
5
  name = TextField("Name",  [validators.Required("Please enter your name.")])
6
  email = TextField("Email",  [validators.Required("Please enter your email address."), validators.Email("Please enter your email address.")])
7
  subject = TextField("Subject",  [validators.Required("Please enter a subject.")])
8
  message = TextAreaField("Message",  [validators.Required("Please enter a message.")])
9
  submit = SubmitField("Send")

Simplemente escribimos mensajes de error específicos dentro de cada validador. A continuación, modifiquemos contact.html para recibir y mostrar estos mensajes de error específicos. Anteriormente, nos basamos en la función get_flashed_messages() para extraer mensajes de error parpadeantes y pasarlos por encima para mostrarlos. Reemplacemos ese bloque con este:

1

2
{% for message in form.name.errors %}
3
  <div class="flash">{{ message }}</div>
4
{% endfor %}
5

6
{% for message in form.email.errors %}
7
  <div class="flash">{{ message }}</div>
8
{% endfor %}
9

10
{% for message in form.subject.errors %}
11
  <div class="flash">{{ message }}</div>
12
{% endfor %}
13

14
{% for message in form.message.errors %}
15
  <div class="flash">{{ message }}</div>
16
{% endfor %}

Aquí usamos el errors atributo para cada campo de formulario para extraer los mensajes de error específicos y recorrerlos usando el Jinja2 for bucle para mostrarlos.

Poniendolo todo junto, contact.html ahora parece esto:

aplicación/plantillas/contacto.html

1

2
{% extends "layout.html" %}
3

4
{% block content %}
5
  <h2>Contact</h2>
6

7
  {% for message in form.name.errors %}
8
    <div class="flash">{{ message }}</div>
9
  {% endfor %}
10

11
  {% for message in form.email.errors %}
12
    <div class="flash">{{ message }}</div>
13
  {% endfor %}
14

15
  {% for message in form.subject.errors %}
16
    <div class="flash">{{ message }}</div>
17
  {% endfor %}
18

19
  {% for message in form.message.errors %}
20
    <div class="flash">{{ message }}</div>
21
  {% endfor %}
22
  
23
  <form action="{{ url_for('contact') }}" method=post>
24
    {{ form.hidden_tag() }}
25

26
    {{ form.name.label }}
27
    {{ form.name }}
28

29
    {{ form.email.label }}
30
    {{ form.email }}
31

32
    {{ form.subject.label }}
33
    {{ form.subject }}
34

35
    {{ form.message.label }}
36
    {{ form.message }}
37

38
    {{ form.submit }}
39
  </form>
40
{% endblock %}

Vuelva al navegador, vaya a http://localhost:5000/contactoy haga clic en «Enviar». Asegúrese de dejar todos los campos del formulario en blanco.

¡Perfecto! El usuario ahora tiene mensajes de error útiles si comete un error.

Punto de control: 09_specific_message_flashing

Logramos mucho en esta sección. Creamos un formulario de contacto desde cero, aprendimos a protegernos contra ataques CSRF, distinguimos entre solicitudes GET y POST, aplicamos validaciones de formularios y mostramos mensajes de error específicos si es necesario. Ahora tenemos que enviar el mensaje por correo electrónico.


Frasco de correo

Frasco de correo es una extensión de Flask que le permite enviar correos electrónicos desde su aplicación Flask. Los pasos a continuación son similares a los que tomamos para usar Flask-WTF.

Comencemos instalando Flask-Mail.

1

2
$ pip install flask-mail

Configuración de Flask-Mail

A continuación, importemos Flask-Mail a routes.py y configurarlo para que podamos empezar a usarlo.

app/rutas.py

1

2
from flask import Flask, render_template, request, flash
3
from forms import ContactForm
4
from flask.ext.mail import Message, Mail
5

6
mail = Mail()
7

8
app = Flask(__name__)
9

10
app.secret_key = 'development key'
11

12
app.config["MAIL_SERVER"] = "smtp.gmail.com"
13
app.config["MAIL_PORT"] = 465
14
app.config["MAIL_USE_SSL"] = True
15
app.config["MAIL_USERNAME"] = 'contact@example.com'
16
app.config["MAIL_PASSWORD"] = 'your-password'
17

18
mail.init_app(app)

Primero, importamos el Message y Mail clases de Flask-Mail (línea tres). Usaremos el Message clase para redactar un nuevo correo electrónico y el Mail clase para enviar el correo electrónico. A continuación, creamos el mail variable que contiene una instancia utilizable de la Mail clase (línea cinco).

Luego configuramos Flask-Mail con algunas configuraciones de servidor SMTP (líneas 11-15). Usé la configuración del servidor SMTP de Gmail aquí, pero puedes usar fácilmente tu proveedor de correo electrónico favorito. Simplemente busque su configuración SMTP y estará listo.

Por ejemplo, si desea utilizar Yahoo! Mail, simplemente busque «configuración del servidor smtp de correo de yahoo» y actualice la configuración.

Asegúrese de ingresar un correo electrónico y una contraseña reales en app.config["MAIL_USERNAME"] y app.config["MAIL_PASSWORD"], respectivamente. Esta será la cuenta desde la que enviará el correo electrónico.

Finalmente, adjuntamos mail a nuestra aplicación Flask para que podamos comenzar a usarla (línea 17).

Probablemente haya visto grupos que usan direcciones de correo electrónico de contacto como contact@example.com o support@example.com. Si posee su propio dominio y puede crear una nueva dirección de correo electrónico de contacto, continúe e ingrese esa dirección de correo electrónico en app.config["MAIL_USERNAME"]. De lo contrario, puede usar su dirección de correo electrónico personal solo para ver cómo funciona.

Enviando un correo electrónico

Ahora que la configuración está completa, vamos a redactar un nuevo correo electrónico que contenga los datos del formulario de contacto y enviarlo. Solo debemos enviar un correo electrónico si se ha enviado el formulario y se han superado todas las comprobaciones de validación. Esto significa que tenemos que trabajar dentro del if request.method == 'POST': bloquear de nuevo. Ya hemos agregado lógica dentro del if form.validate() == False: bloque para manejar fallas de validación. Si pasan todas las comprobaciones de validación, form.validate() estarán True y el programa entrará en el else bloquear. Por lo tanto, sigamos adelante y agreguemos lógica dentro del else: bloquear.

app/rutas.py

1

2
@app.route('/contact', methods=['GET', 'POST'])
3
def contact():
4
  form = ContactForm()
5

6
  if request.method == 'POST':
7
    if form.validate() == False:
8
      flash('All fields are required.')
9
      return render_template('contact.html', form=form)
10
    else:
11
      msg = Message(form.subject.data, sender='contact@example.com', recipients=['your_email@example.com'])
12
      msg.body = """

13
      From: %s <%s>

14
      %s

15
      """ % (form.name.data, form.email.data, form.message.data)
16
      mail.send(msg)
17

18
      return 'Form posted.'
19

20
  elif request.method == 'GET':
21
    return render_template('contact.html', form=form)

Empezamos por redactar un nuevo mensaje (línea 10). Él Message class toma una línea de asunto, una dirección «de» y una dirección «a». A continuación, recopilamos los datos del campo de asunto del formulario de contacto con form.subject.data y configúrelo como la línea de asunto del nuevo mensaje. El correo electrónico se enviará desde la cuenta que configuró en app.config["MAIL_USERNAME"], así que eso es lo que usamos aquí para la dirección de origen. El correo electrónico se enviará a su dirección de correo electrónico personal para que pueda recibir y responder nuevos mensajes.

A continuación, escribimos el propio correo electrónico (líneas 11-14). Incluimos el nombre del usuario, correo electrónico y mensaje. Yo uso el operador de formato de cadena de Python % para formatear el correo electrónico. Y finalmente, usamos mail.send(msg) para enviar el correo electrónico (línea 15).

Vamos a ver si todo funciona. Visitar http://localhost:5000/contacto, complete cada campo y haga clic en «Enviar». Si todo va bien, recibirá un nuevo correo electrónico de su aplicación Flask.

Punto de control: 10_send_email

Poner en orden

Nuestro penúltimo paso es eliminar la cadena de marcador de posición temporal 'Form posted.' con un mensaje agradeciendo al usuario por sus comentarios. Este mensaje solo debería aparecer si nuestra aplicación envía el correo electrónico. Una vez más, esta lógica se puede expresar en un if...else declaración.

Cuando el formulario de contacto se haya enviado correctamente, enviaremos un indicador de éxito desde routes.py a contact.html.

colocaremos el if...else lógica interior contact.html. Si el indicador de éxito se establece en True, mostraremos el mensaje de agradecimiento. De lo contrario, mostraremos el formulario de contacto.

empecemos en routes.py dentro de contact() función. Reemplazar la línea de marcador de posición temporal return 'Form posted.' con return render_template('contact.html', success=True) para enviar una bandera de éxito a contact.html. Él contact() la función ahora se ve así:

app/rutas.py

1

2
@app.route('/contact', methods=['GET', 'POST'])
3
def contact():
4
  form = ContactForm()
5

6
  if request.method == 'POST':
7
    if form.validate() == False:
8
      flash('All fields are required.')
9
      return render_template('contact.html', form=form)
10
    else:
11
      msg = Message(form.subject.data, sender='contact@example.com', recipients=['your_email@example.com'])
12
      msg.body = """

13
      From: %s &lt;%s&gt;

14
      %s

15
      """ % (form.name.data, form.email.data, form.message.data)
16
      mail.send(msg)
17

18
      return render_template('contact.html', success=True)
19

20
  elif request.method == 'GET':
21
    return render_template('contact.html', form=form)

Siguiente abierto contact.html y agrega el if...else lógica. usaremos Jinja2 if...else sintaxis para que esto suceda.

aplicación/plantillas/contacto.html

1

2
{% extends "layout.html" %}
3

4
{% block content %}
5
  <h2>Contact</h2>
6

7
  {% if success %}
8
    <p>Thank you for your message. We'll get back to you shortly.</p>
9

10
  {% else %}
11

12
    {% for message in form.name.errors %}
13
      <div class="flash">{{ message }}</div>
14
    {% endfor %}
15

16
    {% for message in form.email.errors %}
17
      <div class="flash">{{ message }}</div>
18
    {% endfor %}
19

20
    {% for message in form.subject.errors %}
21
      <div class="flash">{{ message }}</div>
22
    {% endfor %}
23

24
    {% for message in form.message.errors %}
25
      <div class="flash">{{ message }}</div>
26
    {% endfor %}
27

28
    <form action="{{ url_for('contact') }}" method=post>
29
      {{ form.hidden_tag() }}
30

31
      {{ form.name.label }}
32
      {{ form.name }}
33

34
      {{ form.email.label }}
35
      {{ form.email }}
36

37
      {{ form.subject.label }}
38
      {{ form.subject }}
39

40
      {{ form.message.label }}
41
      {{ form.message }}
42

43
      {{ form.submit }}
44
    </form>
45

46
  {% endif %}
47
{% endblock %}

Comenzando en la línea seis, {% if success %} significa que si el indicador de éxito que enviamos desde routes.py se establece en Trueluego muestra <p>Thank you for your message. We'll get back to you shortly.</p>. De lo contrario, siga el {% else %} sucursal y mostrar el formulario de contacto. La sintaxis de Jinja2 pide que cerremos la if...else declaración con {% endif %}así que lo incluimos al final (línea 45).

Punto de control: 11_success_message

Finalmente, visitemos http://localhost:5000/contacto Una vez más. Rellene cada campo y haga clic en «Enviar».

Nuestro último paso es agregar un enlace de navegación a la página de contacto. En el artículo anterior, agregamos estos enlaces a layout.html dentro de <header> elemento. También hagámoslo para la página de contacto (línea ocho).

aplicación/plantillas/diseño.html

1

2
<header>
3
  <div class="container">
4
    <h1 class="logo">Flask App</h1>
5
    <nav>
6
      <ul class="menu">
7
        <li><a href="{{ url_for('home') }}">Home</a></li>
8
        <li><a href="{{ url_for('about') }}">About</a></li>
9
        <li><a href="{{ url_for('contact') }}">Contact</a></li>
10
      </ul>
11
    </nav>
12
  </div>
13
</header>

Punto de control: 12_contact_nav_link

Abre el navegador y actualiza http://localhost:5000/ para ver el enlace de navegación recién agregado.


Conclusión

En el artículo, agregamos una página de contacto que contiene un formulario a nuestra aplicación Flask. Los formularios aparecen en varios lugares de las aplicaciones web, sobre todo durante el registro y el inicio de sesión. Este flujo de trabajo se puede adaptar para satisfacer esas necesidades. Al crear una página de contacto, aprendimos a usar las extensiones de Flask.

Las extensiones de Flask son herramientas sencillas y potentes que amplían la funcionalidad de su aplicación basada en Flask.

Revisar la Registro de extensión de matraz para explorar muchas más extensiones que puedes integrar en tu aplicación.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *