Categorías
Python

Una Introducción a roscar en Python

 

Tabla de Contenidos

  • Frasco de registro básico
  • actualización de la función de vista actual commandregister appModelsManage ()
  • Modelos
  • Manejo de comandos
  • registro () función de vista
  • confirmación confirmationGenerate Agregar correo electrónico tokenUpdate registro () vista functionHandle correo electrónico ConfirmationCreate la correo electrónico registro templateSend emailUpdate () función de vista en el proyecto / usuario / views.py (de nuevo!) correo
  • Generar token de confirmación
  • actualización de registro de funciones () vista
  • manija confirmación
  • Crear la plantilla de correo electrónico
  • Enviar correo electrónico
  • actualización de registro () función de vista en el proyecto / usuario / views.py (de nuevo!)
  • correo
  • Primera prueba
  • manija permissionsAdd / sin confirmar routeAdd unconfirmed.html templateUpdate el registro () ver functionCreate un decoratorUpdate navigation.html plantilla
  • Agregar / ruta sin confirmar
  • Añadir unconfirmed.h tml plantilla
  • actualización de la función de vista registro ()
  • Crear un decorador
  • actualización navigation.html plantilla
  • Segunda prueba
  • Reenviar correo electrónico
  • tercera prueba
  • actualización banco de pruebas
  • Conclusión Modelos
  • Manejo de comandos
  • registro () función de vista
  • Generar confirmación símbolo
  • actualización de registro de funciones () vista
  • manija confirmación
  • Cree la vista función de plantilla de correo electrónico
  • Enviar correo electrónico
  • actualización de registro () en el proyecto / usuario / views.py (de nuevo!)
  • correo
  • Agregar / ruta sin confirmar
  • Añadir plantilla unconfirmed.html
  • actualización de la función de vista registro ()
  • Crear un decorador
  • actualización navigation.html plantilla

este tutorial se describe el proceso para validar direcciones de correo electrónico durante el registro de usuario .

Actualizado 04/30/2015 : Agregado Python 3 apoyo.

En términos de flujo de trabajo, después de un usuario se registra una nueva cuenta, se envía un correo electrónico de confirmación. La cuenta de usuario está marcado como “sin confirmar” hasta que el usuario, así, “confirma” la cuenta a través de las instrucciones del correo electrónico. Este es un simple flujo de trabajo que la mayoría de las aplicaciones web siguen.

Una cosa importante a tener en cuenta es lo que los usuarios no confirmados se les permite hacer. En otras palabras, ¿tienen acceso completo a su uso, el acceso limitado / restringido, o ningún acceso en absoluto? Para la aplicación de este tutorial, los usuarios pueden iniciar sesión sin confirmar, pero en la que se redirige inmediatamente a una página que les recuerda que tienen que confirmar su cuenta antes de que puedan acceder a la aplicación.

Antes de empezar, la mayor parte de la funcionalidad que vamos a añadir es parte del matraz de usuario y extensiones matraz de seguridad – lo que plantea la pregunta ¿por qué no usar las extensiones? Bueno, en primer lugar, esta es una oportunidad para aprender. Además, ambos de esos extensiones tienen limitaciones, como las bases de datos compatibles. ¿Qué pasa si desea utilizar RethinkDB, por ejemplo?

vamos a empezar.

Frasco de registro básico

Vamos a empezar con un frasco repetitivo que incluye el registro de usuario básica. Coge el código desde el repositorio. Una vez que haya creado y activado un virtualenv, ejecute los siguientes comandos para comenzar a trabajar rápidamente:

$ pip install -r requirements.txt
$ export APP_SETTINGS="project.config.DevelopmentConfig"
$ python manage.py create_db
$ python manage.py db init
$ python manage.py db migrate
$ python manage.py create_admin
$ python manage.py runserver

Confirmar el readme para más información.

Con la aplicación en ejecución, vaya a http: // localhost: 5000 / y registrar un nuevo usuario. Tenga en cuenta que después del registro, la aplicación que se conecta automáticamente y le redirige a la página principal. Echar un vistazo alrededor, a continuación, ejecute a través del código – en concreto el modelo “usuario”.

Mata al servidor cuando haya terminado.

actualización de la corriente de aplicaciones

Modelos

En primer lugar, vamos a agregar el campo confirmaron a nuestro modelo de usuario en el proyecto / models.py :

class User(db.Model):

__tablename__ = "users"

id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String, unique=True, nullable=False)
password = db.Column(db.String, nullable=False)
registered_on = db.Column(db.DateTime, nullable=False)
admin = db.Column(db.Boolean, nullable=False, default=False)
confirmed = db.Column(db.Boolean, nullable=False, default=False)
confirmed_on = db.Column(db.DateTime, nullable=True)

def __init__(self, email, password, confirmed,
paid=False, admin=False, confirmed_on=None):
self.email = email
self.password = bcrypt.generate_password_hash(password)
self.registered_on = datetime.datetime.now()
self.admin = admin
self.confirmed = confirmed
self.confirmed_on = confirmed_on

Aviso cómo este campo por defecto es ‘falso’. También hemos añadido un campo confirmed_on, que es una fecha y hora. Me gusta incluir este campo y con el fin de analizar la diferencia entre los registered_on y confirmed_on fechas usando análisis de cohortes.

Vamos a empezar completamente de nuevo con nuestra base de datos y las migraciones. Por lo tanto, seguir adelante y eliminar la base de datos, dev.sqlite , así como la carpeta de “migraciones”.

Administrar comandos

A continuación, dentro de manage.py , actualizar el comando create_admin tomar los nuevos campos de la base en cuenta:

@manager.command
def create_admin():
"""Creates the admin user."""
db.session.add(User(
email="ad@min.com",
password="admin",
admin=True,
confirmed=True,
confirmed_on=datetime.datetime.now())
)
db.session.commit()

Asegúrese de importar de fecha y hora. Ahora, seguir adelante y ejecutar los siguientes comandos de nuevo: registro

$ python manage.py create_db
$ python manage.py db init
$ python manage.py db migrate
$ python manage.py create_admin

() función de vista

Por último, antes de que podamos registrar un usuario nuevo, tenemos que hacer un cambio rápido en el registro función de vista () en proyecto / usuario /views.py

Cambio:

user = User(
email=form.email.data,
password=form.password.data
)

Para:

user = User(
email=form.email.data,
password=form.password.data,
confirmed=False
)

sentido? Piense por qué nos gustaría default confirmado en Falso.

bien. Ejecutar la aplicación de nuevo. Vaya a http: // localhost: 5000 / y registrar un nuevo usuario nuevo. Si abre su base de datos SQLite SQLite en el navegador, debería ver:

Así, el nuevo usuario que he registrado, michael@realpython.com, no está confirmado. cambio de dejar que eso.

confirmación Agregar correo electrónico de confirmación

Generar token de

La confirmación de correo electrónico debe contener una URL única que un usuario sólo tiene que hacer clic con el fin de confirmar su / su cuenta. Idealmente, el URL debe ser algo como esto – http://yourapp.com/confirm/ . La clave aquí es el id. Vamos a codificar el correo electrónico del usuario (junto con una marca de tiempo) en el ello utilizando el paquete itsdangerous.

Crear un archivo llamado proyecto / token.py y agregue el siguiente código:

# projectoken.py

from itsdangerous import URLSafeTimedSerializer

from project import app

def generate_confirmation_token(email):
serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
return serializer.dumps(email, salt=app.config['SECURITY_PASSWORD_SALT'])

def confirm_token(token, expiration=3600):
serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
try:
email = serializer.loads(
token,
salt=app.config['SECURITY_PASSWORD_SALT'],
max_age=expiration
)
except:
return False
return email

Por lo tanto, en la función generate_confirmation_token () usamos el URLSafeTimedSerializer para generar un token utilizando la dirección de correo electrónico obtenidos durante el registro del usuario. El correo electrónico real se codifica en el token. Luego, para confirmar el token, dentro de la función confirm_token (), que puede utilizar el método (), que toma la expiración de contadores y cargas – válido durante una hora (3.600 segundos) – como argumentos. Mientras que el token no ha expirado, entonces se volverá un correo electrónico.

Asegúrese de añadir el SECURITY_PASSWORD_SALT de configuración de la aplicación (BaseConfig ()):

SECURITY_PASSWORD_SALT = 'my_precious_two'

actualización función de vista de registro ()

Ahora vamos a actualizar la función de vista registro () de nuevo desde proyecto / usuario / views.py :

@user_blueprint.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm(request.form)
if form.validate_on_submit():
user = User(
email=form.email.data,
password=form.password.data,
confirmed=False
)
db.session.add(user)
db.session.commit()

token = generate_confirmation_token(user.email)

Además, asegúrese de actualizar las importaciones:

from project.token import generate_confirmation_token, confirm_token

manija confirmación

a continuación, vamos a añadir un nuevo punto de vista para manejar el correo electrónico de confirmación:

@user_blueprint.route('/confirm/')
@login_required
def confirm_email(token):
try:
email = confirm_token(token)
except:
flash('The confirmation link is invalid or has expired.', 'danger')
user = User.query.filter_by(email=email).first_or_404()
if user.confirmed:
flash('Account already confirmed. Please login.', 'success')
else:
user.confirmed = True
user.confirmed_on = datetime.datetime.now()
db.session.add(user)
db.session.commit()
flash('You have confirmed your account. Thanks!', 'success')
return redirect(url_for('main.home'))

Añadir este proyecto a / usuario / views.py . También, asegúrese de actualizar las importaciones:

import datetime

Aquí, llamamos a la función confirm_token (), pasando el testigo. Si tiene éxito, actualizamos el usuario, cambiando el atributo email_confirmed en True y establecer la fecha y hora de la confirmación cuando se llevó a cabo. Además, en caso de que el usuario ya pasó por el proceso de confirmación – y se confirma – a continuación, se alerta al usuario de este.

Crear la plantilla de correo electrónico

A continuación, vamos a añadir una plantilla de correo electrónico de base:

Welcome! Thanks for signing up. Please follow this link to activate your account:

{{ confirm_url }}

Cheers!

Guardar esto como activate.html en “Proyecto / templates / usuario”. Este realice una sola variable llamada CONFIRM_URL, que será creado en la función de vista registro ().

Enviar correo electrónico

Vamos a crear una función básica para el envío de mensajes de correo electrónico con un poco de ayuda de frasco-Mail, que ya está instalado y configurado en el proyecto / __ init__.py.

Crear un archivo llamado email.py :

# project/email.py

from flask.ext.mail import Message

from project import app, mail

def send_email(to, subject, template):
msg = Message(
subject,
recipients=[to],
html=template,
sender=app.config['MAIL_DEFAULT_SENDER']
)
mail.send(msg)

Guardar esta en la carpeta de “proyecto”.

Así, simplemente necesita pasar una lista de destinatarios, un asunto y una plantilla. Nos ocuparemos de los valores de configuración de correo electrónico en un poco.

actualización de registro () función de vista en el proyecto / usuario / views.py (¡otra vez!)

@user_blueprint.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm(request.form)
if form.validate_on_submit():
user = User(
email=form.email.data,
password=form.password.data,
confirmed=False
)
db.session.add(user)
db.session.commit()

token = generate_confirmation_token(user.email)
confirm_url = url_for('user.confirm_email', token=token, _external=True)
html = render_template('user/activate.html', confirm_url=confirm_url)
subject = "Please confirm your email"
send_email(user.email, subject, html)

login_user(user)

flash('A confirmation email has been sent via email.', 'success')
return redirect(url_for("main.home"))

return render_template('user/register.html', form=form)

Añadir la siguiente importación, así:

from project.email import send_email

Aquí, estamos poniendo todo junto. Esta función, básicamente, actúa como un controlador (directa o indirectamente) para todo el proceso:

  • Handle registro inicial,
  • Generar token y la confirmación de URL,
  • correo electrónico Enviar confirmación, la confirmación
  • Flash,
  • Entrar en el del usuario, y el usuario
  • redireccionamiento.

¿Se notaron los _external = argumento Cierto? Esto añade la URL completa absoluta que incluye el nombre de host y el puerto (http: // localhost:. 5000, en nuestro caso)

Antes de que podamos probar esto, tenemos que configurar los ajustes de correo.

correo

de inicio mediante la actualización del BaseConfig () en el proyecto / config.py :

class BaseConfig(object):
"""Base configuration."""

# main config
SECRET_KEY = 'my_precious'
SECURITY_PASSWORD_SALT = 'my_precious_two'
DEBUG = False
BCRYPT_LOG_ROUNDS = 13
WTF_CSRF_ENABLED = True
DEBUG_TB_ENABLED = False
DEBUG_TB_INTERCEPT_REDIRECTS = False

# mail settings
MAIL_SERVER = 'smtp.googlemail.com'
MAIL_PORT = 465
MAIL_USE_TLS = False
MAIL_USE_SSL = True

# gmail authentication
MAIL_USERNAME = os.environ['APP_MAIL_USERNAME']
MAIL_PASSWORD = os.environ['APP_MAIL_PASSWORD']

# mail accounts
MAIL_DEFAULT_SENDER = 'from@example.com'

Confirmar la documentación oficial Frasco electrónico para obtener más información.

Si ya tiene una cuenta de GMAIL entonces se puede usar esa o registrar una cuenta de GMAIL prueba. A continuación, establezca las variables de entorno temporalmente en la sesión de shell actual:

$ export APP_MAIL_USERNAME="foo"
$ export APP_MAIL_PASSWORD="bar"

Si su cuenta de GMAIL tiene la autenticación de 2 pasos, Google bloqueará el intento.

Ahora vamos a probar!

Primera prueba de fuego

la aplicación y vaya a http: // localhost: 5000 / registro. A continuación, se registra en una dirección de correo electrónico que tiene acceso. Si todo va bien, debería tener un correo electrónico en su bandeja de entrada que se ve algo como esto:

Haga clic en el URL y lo deben llevar a http: // localhost: 5000 /. Asegúrese de que el usuario se encuentra en la base de datos del campo ‘confirmado’, es cierto, y hay una fecha y hora asociados con el campo confirmed_on.

Nice!

permisos Handle

Si recuerda, al principio de este tutorial, se decidió que “los usuarios no confirmados pueden conectarse pero deben ser redirigidos inmediatamente a una página – Llamemos a la ruta / no confirmada – recordando a los usuarios que necesitan para confirmar su cuenta antes de que puedan acceder a la aplicación”.

Por lo tanto, necesitamos a-

Agregar / ruta sin confirmar

Añadir la siguiente ruta de proyecto / usuario / views.py :

@user_blueprint.route('/unconfirmed')
@login_required
def unconfirmed():
if current_user.confirmed:
return redirect('main.home')
flash('Please confirm your account!', 'warning')
return render_template('user/unconfirmed.html')

Usted ha visto un código similar antes, así que vamos a seguir adelante.

Añadir plantilla unconfirmed.html

{% extends "_base.html" %}

{% block content %}

Welcome!

You have not confirmed your account. Please check your inbox (and your spam folder) - you should have received an email with a confirmation link.

Didn't get the email? Resend.

{% endblock %}

Guardar esto como unconfirmed.html en “Proyecto / templates / usuario”. Una vez más, todo esto debe ser sencillo. Por ahora, hemos añadido una URL maniquí en volver a enviar el correo electrónico de confirmación. Vamos a abordar esta más abajo.

actualización de la función de vista registro ()

Ahora basta con cambiar:

return redirect(url_for("main.home"))

Para:

return redirect(url_for("user.unconfirmed"))

Así, después de que se envió el correo electrónico de confirmación, el usuario está redirigido a la ruta / sin confirmar.

Crear un decorador

# project/decorators.py
from functools import wraps

from flask import flash, redirect, url_for
from flask.ext.login import current_user

def check_confirmed(func):
@wraps(func)
def decorated_function(*args, **kwargs):
if current_user.confirmed is False:
flash('Please confirm your account!', 'warning')
return redirect(url_for('user.unconfirmed'))
return func(*args, **kwargs)

return decorated_function

Aquí tenemos una función básica para comprobar si un usuario no está confirmada. Si no confirmado, el usuario es redirigido a la ruta / sin confirmar. Guardar esto como decorators.py en el directorio “proyecto”.

Ahora, decorar el perfil () función de vista:

@user_blueprint.route('/profile', methods=['GET', 'POST'])
@login_required
@check_confirmed
def profile():
# ... snip ...

Asegúrese de importar el decorador:

from project.decorators import check_confirmed

actualización navigation.html plantilla

Finalmente, actualice la siguiente parte de la plantilla del navigation.html

Cambio :

para:

Es hora de probar otra vez!

Segunda prueba

fuego de la aplicación, y registrar de nuevo con una dirección de correo electrónico que tiene acceso. (No dude en eliminar el antiguo usuario que se registró antes de la primera base de datos utilizar de nuevo.) Ahora usted debe ser redirigido a http: // localhost: 5000 / sin confirmar después del registro.

Asegúrese de probar el http: // localhost: 5000 / perfil de ruta. Esto se debe redirigir a la dirección http: // localhost: 5000 / sin confirmar.

Vaya por delante y confirme el e-mail, y tendrá acceso a todas las páginas. ¡Auge! correo electrónico

Reenviar

Por último, vamos a conseguir el funcionamiento de enlace de reenvío. Agregue la siguiente función de vista a proyecto / usuario / views.py :

@user_blueprint.route('/resend')
@login_required
def resend_confirmation():
token = generate_confirmation_token(current_user.email)
confirm_url = url_for('user.confirm_email', token=token, _external=True)
html = render_template('user/activate.html', confirm_url=confirm_url)
subject = "Please confirm your email"
send_email(current_user.email, subject, html)
flash('A new confirmation email has been sent.', 'success')
return redirect(url_for('user.unconfirmed'))

Ahora actualizar la plantilla unconfirmed.html :

{% extends "_base.html" %}

{% block content %}

Welcome!

You have not confirmed your account. Please check your inbox (and your spam folder) - you should have received an email with a confirmation link.

Didn't get the email? Resend.

{% endblock %}

tercera prueba

Lo de siempre. Esta vez, asegúrese de enviar un nuevo correo electrónico de confirmación y probar el enlace. Deberia de funcionar.

Por último, ¿qué ocurre si se envía a sí mismo un par de enlaces de confirmación? Son cada uno válido? Probarlo. El registro de un nuevo usuario y, a continuación, enviar unos nuevos mensajes de correo electrónico de confirmación. Tratar de confirmar con el primer correo electrónico. ¿Funcionó? Debería. ¿Esta bien? Crees que esos otros mensajes de correo electrónico en caso de expiración, si se envía una nueva?

hacer una investigación sobre esto. Y probar otras aplicaciones web que utiliza. ¿Cómo manejan este tipo de comportamiento?

actualización banco de pruebas

bien. Así que eso es todo por la funcionalidad principal. ¿Qué hay de que se actualice el conjunto de pruebas actual, ya que es, así, roto.

Ejecutar las pruebas:

$ python manage.py test

debería ver el siguiente error:

TypeError: __init__() takes at least 4 arguments (3 given)

Para corregir esto sólo tenemos que actualizar el método () en el proyecto Setup / util.py :

def setUp(self):
db.create_all()
user = User(email="ad@min.com", password="admin_user", confirmed=False)
db.session.add(user)
db.session.commit()

Ahora ejecute de nuevo las pruebas. Todos deben pasar!

Conclusión

claramente hay mucho más que podemos hacer:

descargar todo el código fuente desde el repositorio de Github. Comentar a continuación con preguntas. Echa un vistazo a parte 2. fiestas

felices!

Deja un comentario

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