Extender el UserCreationForm para registrarse con el email

Introducción

El sistema de usuarios en Django tiene un problema y es que por defecto utiliza únicamente el usuario y la contraseña. Sin embargo en la actualidad es cada vez más común que los sitios en lugar de un "nick" utilicen el correo electrónico como usuario:

Ya os enseñé a implementar un sistema clásico de registro, login y logout, así que vamos a extender esa lógica para obligar al usuario a registrarse e iniciar sesión utilizando su correo electrónico:

La solución más sencilla consiste en engañar al usuario, para que en lugar de registrarse con un nombre utilice su correo electrónico.

Extendiendo el registro

Así que vamos a extender el formulario de registro de Django UserCreationForm para que en lugar de Nombre de usuario muestre el texto Correo electrónico. Podemos hacerlo dentro del fichero forms.py y llamaremos al nuevo formulario por ejemplo UCFWithEmail:

forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User

# Extendemos del original
class UCFWithEmail(UserCreationForm):
    # Ahora el campo username es de tipo email y cambiamos su texto
    username = forms.EmailField(label="Correo electrónico")

    class Meta:
        model = User
        fields = ["username", "password1", "password2"]

Ahora en la vista sólo tenemos que cambiar el formulario UserCreationForm por nuestro UCFWithEmail:

# Estas son las líneas que cambian
from .forms import UCFWithEmail
form = UCFWithEmail()
form = UCFWithEmail(data=request.POST)

Y ya lo tendríamos:

Extendiendo el login

Ahora si quisiéramos cambiar el texto Nombre de usuario también en el formulario de login:

Podemos hacer lo mismo extendiendo el formulario AuthenticationForm en nuestro propio AFWithEmail:

forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User

# Extendemos del original
class AFWithEmail(AuthenticationForm):
    # Ahora el campo username es de tipo email y cambiamos su texto
    username = forms.EmailField(label="Correo electrónico")

    class Meta:
        model = User
        fields = ["username", "password"]

Para usarlo en la vista, igual que antes, sólo tenemos que cambiar la clase del formulario por la nuestra.

# Estas son las líneas que cambian
from .forms import UCFWithEmail, AFWithEmail
form = AFWithEmail()
form = AFWithEmail(data=request.POST)

Y listo, ya lo tendremos:

Faltaría sólamente arreglar un detalle durante la validación para que en lugar de Nombre de usuario muestre Correo electrónico, pero es algo tedioso porque el texto se encuentra dentro de las traducciones de Django, sería más fácil diseñar el formulario manualmente, pero bueno, dejando de banda ese detalle esta forma funciona genial:

 

Django 2.2
11/06/2019

Recursos disponibles

attach_file
Código del tutorial