HOWTO · Django
Django Cambiar Contraseña
Aprenderemos con esta explicación sobre cómo creamos una página web para que el usuario cambie la contraseña después de iniciar sesión en la página web en Django.
En esta página
La vista integrada de Django PasswordChangeView permite que un usuario autenticado cambie la contraseña de su cuenta actual. Es distinto del proceso para restablecer una contraseña, que ayuda a recuperar el acceso sin conocer la contraseña actual. La implementación siguiente conecta el formulario, la página de confirmación, los nombres de las URL y un enlace desde la página de inicio.
Configurar las vistas para cambiar la contraseña
En users/views.py, crea una subclase de PasswordChangeView de Django y asígnale la plantilla del formulario. Define success_url con reverse_lazy para que Django resuelva el destino con nombre una vez cargada la configuración de URL. Para la página de confirmación, usa PasswordChangeDoneView; PasswordResetDoneView corresponde al proceso para restablecer una contraseña.
Este ejemplo autónomo de configuración utiliza pequeñas sustituciones de Django para que se puedan revisar los nombres y las conexiones sin un proyecto Django. En tu proyecto, conserva las importaciones y las definiciones de la aplicación, y omite la configuración del arnés y sus aserciones finales. El formulario integrado de Django para cambiar contraseñas valida la contraseña actual enviada y la confirmación de la nueva contraseña mediante los validadores configurados.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
# Harness only: stand-ins let this configuration run without Django installed.
import sys
import types
django = types.ModuleType("django")
contrib = types.ModuleType("django.contrib")
auth = types.ModuleType("django.contrib.auth")
auth_views = types.ModuleType("django.contrib.auth.views")
urls = types.ModuleType("django.urls")
django.__path__ = []
contrib.__path__ = []
auth.__path__ = []
class View:
@classmethod
def as_view(cls):
return cls
class PasswordChangeView(View):
pass
class PasswordChangeDoneView(View):
pass
def reverse_lazy(name):
return name
def path(route, view, name=None):
return (route, view, name)
def include(module, namespace=None):
return (module, namespace)
auth_views.PasswordChangeView = PasswordChangeView
auth_views.PasswordChangeDoneView = PasswordChangeDoneView
urls.reverse_lazy = reverse_lazy
urls.path = path
urls.include = include
sys.modules.update({
"django": django,
"django.contrib": contrib,
"django.contrib.auth": auth,
"django.contrib.auth.views": auth_views,
"django.urls": urls,
})
users_views = types.ModuleType("users_views")
users_views.ChangePasswordView = None
users_views.ChangePasswordDoneView = None
sys.modules["users_views"] = users_views
# users/views.py
from django.contrib.auth.views import PasswordChangeDoneView, PasswordChangeView
from django.urls import reverse_lazy
class ChangePasswordView(PasswordChangeView):
template_name = "users/password-change.html"
success_url = reverse_lazy("users:password-change-done")
class ChangePasswordDoneView(PasswordChangeDoneView):
template_name = "users/password-change-done.html"
users_views.ChangePasswordView = ChangePasswordView
users_views.ChangePasswordDoneView = ChangePasswordDoneView
# users/urls.py
# In the project file, import these classes from .views.
from django.urls import path
from users_views import ChangePasswordDoneView, ChangePasswordView
app_name = "users"
urlpatterns = [
path("change-password/", ChangePasswordView.as_view(), name="password-change"),
path("change-password/done/", ChangePasswordDoneView.as_view(), name="password-change-done"),
]
# project urls.py
from django.urls import include, path
project_urlpatterns = [
path("users/", include("users.urls", namespace="users")),
]
assert ChangePasswordView.success_url == "users:password-change-done"
assert [route[2] for route in urlpatterns] == ["password-change", "password-change-done"]
assert project_urlpatterns[0][1] == ("users.urls", "users")
En tu proyecto, el archivo de URL de la aplicación importa las vistas con from .views import ChangePasswordDoneView, ChangePasswordView; el arnés usa users_views para mantener el ejemplo en un único bloque que pueda ejecutarse por separado. En el archivo de URL del proyecto, importa include y path desde django.urls y usa la misma configuración path("users/", include("users.urls", namespace="users")) que aparece en el arnés.
Registrar los patrones de URL de la aplicación y del proyecto
El arnés anterior incluye ambos niveles de URL. En el proyecto, users/urls.py define app_name = "users", y la configuración de URL del proyecto incluye ese módulo con namespace="users". Juntas, estas definiciones permiten resolver users:password-change-done; los nombres de las rutas de la aplicación y el destino reverse_lazy deben coincidir.
Crear las plantillas para cambiar la contraseña y confirmar el cambio
Crea users/templates/users/password-change.html y haz que extienda la plantilla compartida base.html. Esta plantilla envía el formulario a la misma URL, incluye {% csrf_token %} dentro del formulario y muestra los campos de contraseña actual y nueva con {{ form.as_p }}. El token CSRF contribuye a proteger las solicitudes contra falsificaciones; no sustituye la autenticación ni la validación de la contraseña.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
{% extends 'base.html' %}
{% block title %}Change password{% endblock title %}
{% block content %}
<h1>Change your password</h1>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Change password</button>
</form>
{% endblock content %}
Crea users/templates/users/password-change-done.html para mostrar la respuesta de éxito. Haz que extienda la misma plantilla base, confirma que la contraseña cambió y añade un enlace a la ruta home-view del proyecto. Un POST correcto redirige a esta página; mostrarla por sí solo no cambia ninguna contraseña.
{% extends 'base.html' %}
{% block title %}Password changed{% endblock title %}
{% block content %}
<h1>Your password has been changed</h1>
<a href="{% url 'home-view' %}">Home page</a>
{% endblock content %}
Añadir un enlace desde la página de inicio
En la plantilla de inicio, añade un enlace al formulario con {% url 'users:password-change' %}. La vista integrada de Django para cambiar contraseñas requiere un usuario autenticado, así que coloca el enlace en la navegación para usuarios que hayan iniciado sesión o permite que la vista redirija a quienes no hayan iniciado sesión.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
<a href="{% url 'users:password-change' %}">Change password</a>
Ejecutar y verificar el proceso para cambiar la contraseña
Inicia el proyecto con su configuración de desarrollo habitual, inicia sesión con una cuenta de prueba y sigue el nuevo enlace de la página de inicio. Envía la contraseña actual y un par válido de contraseñas nuevas coincidentes. Confirma que Django redirija a la página de confirmación; después, cierra la sesión e inicia sesión de nuevo con la contraseña nueva. Este es un procedimiento de verificación manual, no un informe de que se haya ejecutado el proceso en el entorno de este artículo.
Una comprobación breve de los nombres de ruta ilustra la relación entre el espacio de nombres y la ruta:
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
app_name = "users"
route_name = "password-change-done"
success_target = f"{app_name}:{route_name}"
print(success_target)
Solucionar errores de configuración frecuentes
Si Django indica que no puede resolver users:password-change-done, comprueba que coincidan app_name, el espacio de nombres de la inclusión del proyecto, el name de la ruta y el destino reverse_lazy. Un error TemplateDoesNotExist suele indicar que la ruta de la plantilla en la vista no coincide con su ubicación bajo el directorio templates/users/ de la aplicación. Revisa la ortografía y asegúrate de que la aplicación esté instalada para que Django detecte sus plantillas.
Si el formulario produce un error CSRF, deja {% csrf_token %} dentro del formulario POST y asegúrate de enviar la página mediante el flujo de solicitudes habitual de Django. Si se redirige a un visitante a la página de inicio de sesión, es lo esperado para esta función destinada a usuarios autenticados; inicia sesión antes de probar el cambio de contraseña. Si aparece la página de confirmación pero la contraseña no cambió, verifica que el formulario se envíe a la vista y que la contraseña actual y la confirmación de la nueva contraseña cumplan los validadores del proyecto.