Formulario de registro
Django proporciona UserCreationForm como punto de partida para el registro. Se puede extender para añadir campos adicionales:
# usuarios/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import get_user_model
Usuario = get_user_model()
class FormularioRegistro(UserCreationForm):
email = forms.EmailField(required=True, help_text='Requerido. Recibirás notificaciones aquí.')
nombre = forms.CharField(max_length=50, required=True)
apellidos = forms.CharField(max_length=100, required=False)
acepto_terminos = forms.BooleanField(
required=True,
error_messages={'required': 'Debes aceptar los términos y condiciones.'}
)
class Meta(UserCreationForm.Meta):
model = Usuario
fields = ['username', 'email', 'nombre', 'apellidos', 'password1', 'password2']
def clean_email(self):
email = self.cleaned_data.get('email').lower()
if Usuario.objects.filter(email=email).exists():
raise forms.ValidationError('Ya existe una cuenta con este email.')
return email
def save(self, commit=True):
usuario = super().save(commit=False)
usuario.email = self.cleaned_data['email']
usuario.first_name = self.cleaned_data.get('nombre', '')
usuario.last_name = self.cleaned_data.get('apellidos', '')
if commit:
usuario.save()
return usuario

Vista de registro
# usuarios/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.contrib import messages
from .forms import FormularioRegistro
def registro(request):
if request.user.is_authenticated:
return redirect('dashboard')
if request.method == 'POST':
form = FormularioRegistro(request.POST)
if form.is_valid():
usuario = form.save()
login(request, usuario) # Login automático tras registro
messages.success(
request,
f'¡Bienvenido/a, {usuario.get_full_name() or usuario.username}! Tu cuenta ha sido creada.'
)
return redirect('dashboard')
else:
form = FormularioRegistro()
return render(request, 'usuarios/registro.html', {'form': form})
Modelo Perfil con señal post_save
Para datos adicionales del usuario que no caben en el modelo User, se crea un modelo Perfil relacionado y se crea automáticamente al crear el usuario:
# usuarios/models.py
from django.db import models
from django.conf import settings
class Perfil(models.Model):
usuario = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='perfil'
)
avatar = models.ImageField(upload_to='avatares/', blank=True, null=True)
bio = models.TextField(blank=True, max_length=500)
ciudad = models.CharField(max_length=100, blank=True)
sitio_web = models.URLField(blank=True)
fecha_nacimiento = models.DateField(null=True, blank=True)
def __str__(self):
return f'Perfil de {self.usuario.username}'
# usuarios/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model
from .models import Perfil
Usuario = get_user_model()
@receiver(post_save, sender=Usuario)
def crear_o_actualizar_perfil(sender, instance, created, **kwargs):
if created:
Perfil.objects.create(usuario=instance)
else:
# Guardar el perfil si ya existe (para sincronizar cambios)
if hasattr(instance, 'perfil'):
instance.perfil.save()
Conecta las señales en AppConfig:
# usuarios/apps.py
from django.apps import AppConfig
class UsuariosConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'usuarios'
def ready(self):
import usuarios.signals # Conecta las señales al iniciar la app
Vista de edición de perfil
# usuarios/forms.py
class FormularioPerfil(forms.ModelForm):
class Meta:
model = Perfil
fields = ['avatar', 'bio', 'ciudad', 'sitio_web', 'fecha_nacimiento']
widgets = {
'fecha_nacimiento': forms.DateInput(attrs={'type': 'date'}),
'bio': forms.Textarea(attrs={'rows': 3}),
}
class FormularioDatosUsuario(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ['first_name', 'last_name', 'email']
# usuarios/views.py
from django.contrib.auth.decorators import login_required
from .forms import FormularioPerfil, FormularioDatosUsuario
@login_required
def editar_perfil(request):
if request.method == 'POST':
form_usuario = FormularioDatosUsuario(request.POST, instance=request.user)
form_perfil = FormularioPerfil(request.POST, request.FILES, instance=request.user.perfil)
if form_usuario.is_valid() and form_perfil.is_valid():
form_usuario.save()
form_perfil.save()
messages.success(request, 'Perfil actualizado correctamente.')
return redirect('mi-perfil')
else:
form_usuario = FormularioDatosUsuario(instance=request.user)
form_perfil = FormularioPerfil(instance=request.user.perfil)
return render(request, 'usuarios/editar_perfil.html', {
'form_usuario': form_usuario,
'form_perfil': form_perfil,
})
@login_required
def mi_perfil(request):
return render(request, 'usuarios/perfil.html', {'perfil': request.user.perfil})
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Django
Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Crear un formulario de registro extendiendo UserCreationForm. Implementar la vista de registro con validación y redirección al login. Crear automáticamente el perfil del usuario con la señal post_save. Implementar la vista de perfil con edición de datos personales. Permitir al usuario cambiar su contraseña desde su perfil.