feat: added recover password view
This commit is contained in:
@@ -43,6 +43,7 @@ EMAIL_HOST = env.str('EMAIL_HOST', '')
|
|||||||
EMAIL_HOST_USER = env.str('EMAIL_HOST_USER', '')
|
EMAIL_HOST_USER = env.str('EMAIL_HOST_USER', '')
|
||||||
EMAIL_HOST_PASSWORD = env.str('EMAIL_HOST_PASSWORD', '')
|
EMAIL_HOST_PASSWORD = env.str('EMAIL_HOST_PASSWORD', '')
|
||||||
EMAIL_PORT = env.int('EMAIL_PORT', 587)
|
EMAIL_PORT = env.int('EMAIL_PORT', 587)
|
||||||
|
DEFAULT_FROM_EMAIL = env.str('DEFAULT_FROM_EMAIL', 'webmaster@localhost')
|
||||||
|
|
||||||
# Nivel de log de la app y de Django (ver LOGGING en base.py). En producción
|
# Nivel de log de la app y de Django (ver LOGGING en base.py). En producción
|
||||||
# (DEBUG=False) Django, por defecto, solo manda los errores por email a
|
# (DEBUG=False) Django, por defecto, solo manda los errores por email a
|
||||||
|
|||||||
+29
-1
@@ -1,5 +1,11 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm, UserCreationForm
|
from django.contrib.auth.forms import (
|
||||||
|
AuthenticationForm,
|
||||||
|
PasswordChangeForm,
|
||||||
|
PasswordResetForm,
|
||||||
|
SetPasswordForm,
|
||||||
|
UserCreationForm,
|
||||||
|
)
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
# Los formularios de auth de Django no traen ninguna clase CSS en sus
|
# Los formularios de auth de Django no traen ninguna clase CSS en sus
|
||||||
@@ -18,6 +24,14 @@ class StyledAuthenticationForm(AuthenticationForm):
|
|||||||
|
|
||||||
|
|
||||||
class StyledUserCreationForm(UserCreationForm):
|
class StyledUserCreationForm(UserCreationForm):
|
||||||
|
# UserCreationForm no pide email por defecto (piensa solo en
|
||||||
|
# usuario/contraseña); sin él, PasswordResetForm no tiene a qué
|
||||||
|
# dirección mandar el enlace de recuperación de estos usuarios.
|
||||||
|
email = forms.EmailField(label=_('Email'))
|
||||||
|
|
||||||
|
class Meta(UserCreationForm.Meta):
|
||||||
|
fields = ('username', 'email')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
for field in self.fields.values():
|
for field in self.fields.values():
|
||||||
@@ -31,6 +45,20 @@ class StyledPasswordChangeForm(PasswordChangeForm):
|
|||||||
field.widget.attrs['class'] = INPUT_CLASSES
|
field.widget.attrs['class'] = INPUT_CLASSES
|
||||||
|
|
||||||
|
|
||||||
|
class StyledPasswordResetForm(PasswordResetForm):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
for field in self.fields.values():
|
||||||
|
field.widget.attrs['class'] = INPUT_CLASSES
|
||||||
|
|
||||||
|
|
||||||
|
class StyledSetPasswordForm(SetPasswordForm):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
for field in self.fields.values():
|
||||||
|
field.widget.attrs['class'] = INPUT_CLASSES
|
||||||
|
|
||||||
|
|
||||||
class EmailUpdateForm(forms.Form):
|
class EmailUpdateForm(forms.Form):
|
||||||
email = forms.EmailField(label=_('Email'), widget=forms.EmailInput(attrs={'class': INPUT_CLASSES}))
|
email = forms.EmailField(label=_('Email'), widget=forms.EmailInput(attrs={'class': INPUT_CLASSES}))
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: crochet\n"
|
"Project-Id-Version: crochet\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-07-20 10:46+0000\n"
|
"POT-Creation-Date: 2026-07-21 10:20+0000\n"
|
||||||
"Language: en\n"
|
"Language: en\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: crochet/forms.py:35 crochet/templates/crochet/account_settings.html:22
|
#: crochet/forms.py:30 crochet/forms.py:63
|
||||||
|
#: crochet/templates/crochet/account_settings.html:22
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "Email"
|
msgstr "Email"
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ msgstr "Password updated."
|
|||||||
|
|
||||||
#: crochet/templates/crochet/_account_password_form.html:19
|
#: crochet/templates/crochet/_account_password_form.html:19
|
||||||
#: crochet/templates/crochet/account_settings.html:29
|
#: crochet/templates/crochet/account_settings.html:29
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:30
|
||||||
msgid "Cambiar contraseña"
|
msgid "Cambiar contraseña"
|
||||||
msgstr "Change password"
|
msgstr "Change password"
|
||||||
|
|
||||||
@@ -57,13 +59,12 @@ msgid "Actualizado el %(date)s"
|
|||||||
msgstr "Updated on %(date)s"
|
msgstr "Updated on %(date)s"
|
||||||
|
|
||||||
#: crochet/templates/crochet/account_home.html:44
|
#: crochet/templates/crochet/account_home.html:44
|
||||||
#: crochet/templates/crochet/pattern.html:158
|
#: crochet/templates/crochet/pattern.html:163
|
||||||
#: crochet/templates/crochet/pattern.html:204
|
|
||||||
msgid "Vista previa"
|
msgid "Vista previa"
|
||||||
msgstr "Preview"
|
msgstr "Preview"
|
||||||
|
|
||||||
#: crochet/templates/crochet/account_home.html:48
|
#: crochet/templates/crochet/account_home.html:48
|
||||||
#: crochet/templates/crochet/pattern.html:50
|
#: crochet/templates/crochet/pattern.html:55
|
||||||
msgid "Eliminar"
|
msgid "Eliminar"
|
||||||
msgstr "Delete"
|
msgstr "Delete"
|
||||||
|
|
||||||
@@ -91,16 +92,12 @@ msgstr "Log out"
|
|||||||
|
|
||||||
#: crochet/templates/crochet/base.html:62
|
#: crochet/templates/crochet/base.html:62
|
||||||
#: crochet/templates/crochet/home.html:24
|
#: crochet/templates/crochet/home.html:24
|
||||||
|
#: crochet/templates/crochet/password_reset_complete.html:18
|
||||||
#: crochet/templates/registration/login.html:4
|
#: crochet/templates/registration/login.html:4
|
||||||
#: crochet/templates/registration/login.html:14
|
#: crochet/templates/registration/login.html:14
|
||||||
msgid "Iniciar sesión"
|
msgid "Iniciar sesión"
|
||||||
msgstr "Log in"
|
msgstr "Log in"
|
||||||
|
|
||||||
#: crochet/templates/crochet/base.html:63
|
|
||||||
#: crochet/templates/registration/register.html:29
|
|
||||||
msgid "Registrarme"
|
|
||||||
msgstr "Sign up"
|
|
||||||
|
|
||||||
#: crochet/templates/crochet/home.html:4
|
#: crochet/templates/crochet/home.html:4
|
||||||
msgid "Crochet — Crea y comparte tus patrones"
|
msgid "Crochet — Crea y comparte tus patrones"
|
||||||
msgstr "Crochet — Create and share your patterns"
|
msgstr "Crochet — Create and share your patterns"
|
||||||
@@ -161,233 +158,328 @@ msgstr ""
|
|||||||
"Send your pattern to anyone with a read-only link: no one else will be able "
|
"Send your pattern to anyone with a read-only link: no one else will be able "
|
||||||
"to edit it."
|
"to edit it."
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_complete.html:4
|
||||||
|
#: crochet/templates/crochet/password_reset_complete.html:14
|
||||||
|
msgid "Contraseña actualizada"
|
||||||
|
msgstr "Password updated"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_complete.html:16
|
||||||
|
msgid "Ya puedes iniciar sesión con tu nueva contraseña."
|
||||||
|
msgstr "You can now log in with your new password."
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:4
|
||||||
|
msgid "Elegir nueva contraseña"
|
||||||
|
msgstr "Choose new password"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:15
|
||||||
|
msgid "Elige una contraseña nueva"
|
||||||
|
msgstr "Choose a new password"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:33
|
||||||
|
msgid "Enlace no válido"
|
||||||
|
msgstr "Invalid link"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:35
|
||||||
|
msgid ""
|
||||||
|
"El enlace para restablecer la contraseña no es válido, puede que ya se haya "
|
||||||
|
"usado. Solicita uno nuevo."
|
||||||
|
msgstr ""
|
||||||
|
"The password reset link is invalid, possibly because it has already been "
|
||||||
|
"used. Please request a new one."
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:38
|
||||||
|
msgid "Solicitar un enlace nuevo"
|
||||||
|
msgstr "Request a new link"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_done.html:4
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:4
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:14
|
||||||
|
msgid "Recuperar contraseña"
|
||||||
|
msgstr "Reset password"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_done.html:14
|
||||||
|
msgid "Revisa tu email"
|
||||||
|
msgstr "Check your email"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_done.html:16
|
||||||
|
msgid ""
|
||||||
|
"Si existe una cuenta con ese email, te hemos enviado un enlace para elegir "
|
||||||
|
"una contraseña nueva."
|
||||||
|
msgstr ""
|
||||||
|
"If an account exists with that email, we've sent you a link to choose a new "
|
||||||
|
"password."
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_done.html:19
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:32
|
||||||
|
msgid "Volver a iniciar sesión"
|
||||||
|
msgstr "Back to login"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_email.html:2
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"Has recibido este email porque alguien ha solicitado restablecer la "
|
||||||
|
"contraseña de tu cuenta en %(site_name)s."
|
||||||
|
msgstr ""
|
||||||
|
"You're receiving this email because someone requested a password reset for "
|
||||||
|
"your account at %(site_name)s."
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_email.html:4
|
||||||
|
msgid "Sigue este enlace para elegir una contraseña nueva:"
|
||||||
|
msgstr "Follow this link to choose a new password:"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_email.html:7
|
||||||
|
msgid "Tu usuario, por si lo has olvidado:"
|
||||||
|
msgstr "Your username, in case you've forgotten:"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_email.html:9
|
||||||
|
msgid "Si no has solicitado este cambio, puedes ignorar este email."
|
||||||
|
msgstr "If you didn't request this change, you can ignore this email."
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:16
|
||||||
|
msgid ""
|
||||||
|
"Escribe tu email y te enviaremos un enlace para elegir una contraseña nueva."
|
||||||
|
msgstr "Enter your email and we'll send you a link to choose a new password."
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:29
|
||||||
|
msgid "Enviar enlace"
|
||||||
|
msgstr "Send link"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_subject.txt:1
|
||||||
|
#, python-format
|
||||||
|
msgid "Recupera tu contraseña en %(site_name)s"
|
||||||
|
msgstr "Reset your password on %(site_name)s"
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/pattern.html:26
|
||||||
|
msgid "Idioma del patrón"
|
||||||
|
msgstr "Pattern language"
|
||||||
|
|
||||||
# crochet/templates/crochet/pattern.html
|
# crochet/templates/crochet/pattern.html
|
||||||
#: crochet/templates/crochet/pattern.html:33
|
#: crochet/templates/crochet/pattern.html:38
|
||||||
msgid "No se ha podido guardar. Inténtalo de nuevo."
|
msgid "No se ha podido guardar. Inténtalo de nuevo."
|
||||||
msgstr "Couldn't save. Please try again."
|
msgstr "Couldn't save. Please try again."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:33
|
#: crochet/templates/crochet/pattern.html:38
|
||||||
msgid "Guardar"
|
msgid "Guardar"
|
||||||
msgstr "Save"
|
msgstr "Save"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:36
|
#: crochet/templates/crochet/pattern.html:41
|
||||||
msgid "Ver patrón"
|
msgid "Ver patrón"
|
||||||
msgstr "View pattern"
|
msgstr "View pattern"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:37
|
#: crochet/templates/crochet/pattern.html:42
|
||||||
msgid "Exportar a PDF"
|
msgid "Exportar a PDF"
|
||||||
msgstr "Export to PDF"
|
msgstr "Export to PDF"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:44
|
#: crochet/templates/crochet/pattern.html:49
|
||||||
msgid "Más opciones"
|
msgid "Más opciones"
|
||||||
msgstr "More options"
|
msgstr "More options"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:60
|
#: crochet/templates/crochet/pattern.html:65
|
||||||
msgid "Guardado"
|
msgid "Guardado"
|
||||||
msgstr "Saved"
|
msgstr "Saved"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:67
|
#: crochet/templates/crochet/pattern.html:72
|
||||||
msgid "Personalización de página"
|
msgid "Personalización de página"
|
||||||
msgstr "Page customization"
|
msgstr "Page customization"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:71
|
#: crochet/templates/crochet/pattern.html:76
|
||||||
msgid "Título del patrón"
|
msgid "Título del patrón"
|
||||||
msgstr "Pattern title"
|
msgstr "Pattern title"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:72
|
#: crochet/templates/crochet/pattern.html:77
|
||||||
msgid "Título del patrón..."
|
msgid "Título del patrón..."
|
||||||
msgstr "Pattern title..."
|
msgstr "Pattern title..."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:75
|
#: crochet/templates/crochet/pattern.html:80
|
||||||
msgid "Autor"
|
msgid "Autor"
|
||||||
msgstr "Author"
|
msgstr "Author"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:76
|
#: crochet/templates/crochet/pattern.html:81
|
||||||
msgid "Autor..."
|
msgid "Autor..."
|
||||||
msgstr "Author..."
|
msgstr "Author..."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:81
|
#: crochet/templates/crochet/pattern.html:86
|
||||||
msgid "Imagen de portada"
|
msgid "Imagen de portada"
|
||||||
msgstr "Cover image"
|
msgstr "Cover image"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:84
|
#: crochet/templates/crochet/pattern.html:89
|
||||||
msgid "No se ha podido subir la imagen de portada. Inténtalo de nuevo."
|
msgid "No se ha podido subir la imagen de portada. Inténtalo de nuevo."
|
||||||
msgstr "Couldn't upload the cover image. Please try again."
|
msgstr "Couldn't upload the cover image. Please try again."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:98
|
#: crochet/templates/crochet/pattern.html:103
|
||||||
#: crochet/templates/crochet/pattern.html:182
|
#: crochet/templates/crochet/pattern.html:187
|
||||||
msgid "Color del texto"
|
msgid "Color del texto"
|
||||||
msgstr "Text color"
|
msgstr "Text color"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:102
|
#: crochet/templates/crochet/pattern.html:107
|
||||||
msgid "Color de acento (títulos)"
|
msgid "Color de acento (títulos)"
|
||||||
msgstr "Accent color (headings)"
|
msgstr "Accent color (headings)"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:106
|
#: crochet/templates/crochet/pattern.html:111
|
||||||
#: crochet/templates/crochet/pattern.html:182
|
#: crochet/templates/crochet/pattern.html:187
|
||||||
msgid "Color de fondo"
|
msgid "Color de fondo"
|
||||||
msgstr "Background color"
|
msgstr "Background color"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:110
|
#: crochet/templates/crochet/pattern.html:115
|
||||||
msgid "Tipografía"
|
msgid "Tipografía"
|
||||||
msgstr "Font"
|
msgstr "Font"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:116
|
#: crochet/templates/crochet/pattern.html:121
|
||||||
msgid "Monoespaciada"
|
msgid "Monoespaciada"
|
||||||
msgstr "Monospace"
|
msgstr "Monospace"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:120
|
#: crochet/templates/crochet/pattern.html:125
|
||||||
msgid "Tamaño de letra"
|
msgid "Tamaño de letra"
|
||||||
msgstr "Font size"
|
msgstr "Font size"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:122
|
#: crochet/templates/crochet/pattern.html:127
|
||||||
msgid "Pequeño"
|
msgid "Pequeño"
|
||||||
msgstr "Small"
|
msgstr "Small"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:123
|
#: crochet/templates/crochet/pattern.html:128
|
||||||
msgid "Normal"
|
msgid "Normal"
|
||||||
msgstr "Normal"
|
msgstr "Normal"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:124
|
#: crochet/templates/crochet/pattern.html:129
|
||||||
msgid "Grande"
|
msgid "Grande"
|
||||||
msgstr "Large"
|
msgstr "Large"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:128
|
#: crochet/templates/crochet/pattern.html:133
|
||||||
msgid "Alineación del texto"
|
msgid "Alineación del texto"
|
||||||
msgstr "Text alignment"
|
msgstr "Text alignment"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:130
|
#: crochet/templates/crochet/pattern.html:135
|
||||||
msgid "Izquierda"
|
msgid "Izquierda"
|
||||||
msgstr "Left"
|
msgstr "Left"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:131
|
#: crochet/templates/crochet/pattern.html:136
|
||||||
msgid "Centrado"
|
msgid "Centrado"
|
||||||
msgstr "Center"
|
msgstr "Center"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:132
|
#: crochet/templates/crochet/pattern.html:137
|
||||||
msgid "Justificado"
|
msgid "Justificado"
|
||||||
msgstr "Justify"
|
msgstr "Justify"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:136
|
#: crochet/templates/crochet/pattern.html:141
|
||||||
msgid "Tamaño de página"
|
msgid "Tamaño de página"
|
||||||
msgstr "Page size"
|
msgstr "Page size"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:141
|
#: crochet/templates/crochet/pattern.html:146
|
||||||
msgid "Carta (Letter)"
|
msgid "Carta (Letter)"
|
||||||
msgstr "Letter"
|
msgstr "Letter"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:146
|
#: crochet/templates/crochet/pattern.html:151
|
||||||
msgid "Orientación"
|
msgid "Orientación"
|
||||||
msgstr "Orientation"
|
msgstr "Orientation"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:148
|
#: crochet/templates/crochet/pattern.html:153
|
||||||
msgid "Vertical"
|
msgid "Vertical"
|
||||||
msgstr "Portrait"
|
msgstr "Portrait"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:149
|
#: crochet/templates/crochet/pattern.html:154
|
||||||
msgid "Horizontal"
|
msgid "Horizontal"
|
||||||
msgstr "Landscape"
|
msgstr "Landscape"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:157
|
#: crochet/templates/crochet/pattern.html:162
|
||||||
#: crochet/templates/crochet/pattern.html:165
|
#: crochet/templates/crochet/pattern.html:170
|
||||||
msgid "Secciones"
|
msgid "Secciones"
|
||||||
msgstr "Sections"
|
msgstr "Sections"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:167
|
#: crochet/templates/crochet/pattern.html:172
|
||||||
msgid "Colapsar todo"
|
msgid "Colapsar todo"
|
||||||
msgstr "Collapse all"
|
msgstr "Collapse all"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:167
|
#: crochet/templates/crochet/pattern.html:172
|
||||||
msgid "Expandir todo"
|
msgid "Expandir todo"
|
||||||
msgstr "Expand all"
|
msgstr "Expand all"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:172
|
#: crochet/templates/crochet/pattern.html:177
|
||||||
msgid "Añadir sección"
|
msgid "Añadir sección"
|
||||||
msgstr "Add section"
|
msgstr "Add section"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:175
|
#: crochet/templates/crochet/pattern.html:180
|
||||||
msgid "Título"
|
msgid "Título"
|
||||||
msgstr "Title"
|
msgstr "Title"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:175
|
#: crochet/templates/crochet/pattern.html:180
|
||||||
msgid "Título..."
|
msgid "Título..."
|
||||||
msgstr "Title..."
|
msgstr "Title..."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:177
|
#: crochet/templates/crochet/pattern.html:182
|
||||||
msgid "Subtítulo"
|
msgid "Subtítulo"
|
||||||
msgstr "Subtitle"
|
msgstr "Subtitle"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:177
|
#: crochet/templates/crochet/pattern.html:182
|
||||||
msgid "Subtítulo..."
|
msgid "Subtítulo..."
|
||||||
msgstr "Subtitle..."
|
msgstr "Subtitle..."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:179
|
#: crochet/templates/crochet/pattern.html:184
|
||||||
msgid "Texto"
|
msgid "Texto"
|
||||||
msgstr "Text"
|
msgstr "Text"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:179
|
#: crochet/templates/crochet/pattern.html:184
|
||||||
msgid "Escribe aquí..."
|
msgid "Escribe aquí..."
|
||||||
msgstr "Write here..."
|
msgstr "Write here..."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:181
|
#: crochet/templates/crochet/pattern.html:186
|
||||||
#: crochet/templates/crochet/pattern.html:182
|
#: crochet/templates/crochet/pattern.html:187
|
||||||
msgid "Nota"
|
msgid "Nota"
|
||||||
msgstr "Note"
|
msgstr "Note"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:181
|
#: crochet/templates/crochet/pattern.html:186
|
||||||
msgid "Escribe una nota o consejo..."
|
msgid "Escribe una nota o consejo..."
|
||||||
msgstr "Write a note or tip..."
|
msgstr "Write a note or tip..."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:184
|
#: crochet/templates/crochet/pattern.html:189
|
||||||
msgid "Materiales"
|
msgid "Materiales"
|
||||||
msgstr "Materials"
|
msgstr "Materials"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:184
|
#: crochet/templates/crochet/pattern.html:189
|
||||||
msgid "Añadir material..."
|
msgid "Añadir material..."
|
||||||
msgstr "Add material..."
|
msgstr "Add material..."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:184
|
#: crochet/templates/crochet/pattern.html:189
|
||||||
msgid "Añadir línea"
|
msgid "Añadir línea"
|
||||||
msgstr "Add line"
|
msgstr "Add line"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:186
|
#: crochet/templates/crochet/pattern.html:191
|
||||||
#: crochet/templates/crochet/pattern.html:188
|
#: crochet/templates/crochet/pattern.html:193
|
||||||
msgid "Imagen"
|
msgid "Imagen"
|
||||||
msgstr "Image"
|
msgstr "Image"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:188
|
#: crochet/templates/crochet/pattern.html:193
|
||||||
msgid "No se ha podido subir la imagen. Inténtalo de nuevo."
|
msgid "No se ha podido subir la imagen. Inténtalo de nuevo."
|
||||||
msgstr "Couldn't upload the image. Please try again."
|
msgstr "Couldn't upload the image. Please try again."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:190
|
#: crochet/templates/crochet/pattern.html:195
|
||||||
msgid "Patrón"
|
msgid "Patrón"
|
||||||
msgstr "Pattern"
|
msgstr "Pattern"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:190
|
#: crochet/templates/crochet/pattern.html:195
|
||||||
msgid "Elementos"
|
msgid "Elementos"
|
||||||
msgstr "Elements"
|
msgstr "Elements"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:192
|
#: crochet/templates/crochet/pattern.html:197
|
||||||
msgid "Grupo"
|
msgid "Grupo"
|
||||||
msgstr "Group"
|
msgstr "Group"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:196
|
#: crochet/templates/crochet/pattern.html:201
|
||||||
msgid "Arrastrar para reordenar"
|
msgid "Arrastrar para reordenar"
|
||||||
msgstr "Drag to reorder"
|
msgstr "Drag to reorder"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:197
|
#: crochet/templates/crochet/pattern.html:202
|
||||||
msgid "Colapsar / expandir"
|
msgid "Colapsar / expandir"
|
||||||
msgstr "Collapse / expand"
|
msgstr "Collapse / expand"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:198
|
#: crochet/templates/crochet/pattern.html:203
|
||||||
msgid "Duplicar sección"
|
msgid "Duplicar sección"
|
||||||
msgstr "Duplicate section"
|
msgstr "Duplicate section"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:199
|
#: crochet/templates/crochet/pattern.html:204
|
||||||
msgid "Eliminar sección"
|
msgid "Eliminar sección"
|
||||||
msgstr "Delete section"
|
msgstr "Delete section"
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:200
|
#: crochet/templates/crochet/pattern.html:205
|
||||||
msgid ""
|
msgid ""
|
||||||
"¿Seguro que quieres eliminar este grupo? Se eliminarán también todas las "
|
"¿Seguro que quieres eliminar este grupo? Se eliminarán también todas las "
|
||||||
"secciones que contiene."
|
"secciones que contiene."
|
||||||
@@ -395,7 +487,7 @@ msgstr ""
|
|||||||
"Are you sure you want to delete this group? All sections inside it will also "
|
"Are you sure you want to delete this group? All sections inside it will also "
|
||||||
"be deleted."
|
"be deleted."
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:206
|
#: crochet/templates/crochet/pattern.html:210
|
||||||
msgid "Añade una sección para ver aquí el resultado."
|
msgid "Añade una sección para ver aquí el resultado."
|
||||||
msgstr "Add a section to see the result here."
|
msgstr "Add a section to see the result here."
|
||||||
|
|
||||||
@@ -412,6 +504,10 @@ msgid "Entrar"
|
|||||||
msgstr "Log in"
|
msgstr "Log in"
|
||||||
|
|
||||||
#: crochet/templates/registration/login.html:32
|
#: crochet/templates/registration/login.html:32
|
||||||
|
msgid "¿Has olvidado tu contraseña?"
|
||||||
|
msgstr "Forgot your password?"
|
||||||
|
|
||||||
|
#: crochet/templates/registration/login.html:35
|
||||||
msgid "¿No tienes cuenta? Regístrate"
|
msgid "¿No tienes cuenta? Regístrate"
|
||||||
msgstr "Don't have an account? Sign up"
|
msgstr "Don't have an account? Sign up"
|
||||||
|
|
||||||
@@ -420,6 +516,10 @@ msgstr "Don't have an account? Sign up"
|
|||||||
msgid "Crear cuenta"
|
msgid "Crear cuenta"
|
||||||
msgstr "Create account"
|
msgstr "Create account"
|
||||||
|
|
||||||
|
#: crochet/templates/registration/register.html:29
|
||||||
|
msgid "Registrarme"
|
||||||
|
msgstr "Sign up"
|
||||||
|
|
||||||
#: crochet/templates/registration/register.html:32
|
#: crochet/templates/registration/register.html:32
|
||||||
msgid "¿Ya tienes cuenta? Inicia sesión"
|
msgid "¿Ya tienes cuenta? Inicia sesión"
|
||||||
msgstr "Already have an account? Log in"
|
msgstr "Already have an account? Log in"
|
||||||
@@ -484,6 +584,22 @@ msgstr ""
|
|||||||
msgid "account/logout/"
|
msgid "account/logout/"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/urls.py:60
|
||||||
|
msgid "account/password-reset/"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/urls.py:75
|
||||||
|
msgid "account/password-reset/done/"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/urls.py:79
|
||||||
|
msgid "account/reset/<uidb64>/<token>/"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/urls.py:87
|
||||||
|
msgid "account/reset/done/"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# crochet/views.py (PatternDetailView.EMPTY_MESSAGE)
|
# crochet/views.py (PatternDetailView.EMPTY_MESSAGE)
|
||||||
#: crochet/views.py:24
|
#: crochet/views.py:24
|
||||||
msgid "Este patrón todavía no tiene contenido."
|
msgid "Este patrón todavía no tiene contenido."
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: crochet\n"
|
"Project-Id-Version: crochet\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-07-20 10:46+0000\n"
|
"POT-Creation-Date: 2026-07-21 10:20+0000\n"
|
||||||
"Language: es\n"
|
"Language: es\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: crochet/forms.py:35 crochet/templates/crochet/account_settings.html:22
|
#: crochet/forms.py:30 crochet/forms.py:63
|
||||||
|
#: crochet/templates/crochet/account_settings.html:22
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: crochet/templates/crochet/_account_password_form.html:19
|
#: crochet/templates/crochet/_account_password_form.html:19
|
||||||
#: crochet/templates/crochet/account_settings.html:29
|
#: crochet/templates/crochet/account_settings.html:29
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:30
|
||||||
msgid "Cambiar contraseña"
|
msgid "Cambiar contraseña"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -57,13 +59,12 @@ msgid "Actualizado el %(date)s"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/account_home.html:44
|
#: crochet/templates/crochet/account_home.html:44
|
||||||
#: crochet/templates/crochet/pattern.html:158
|
#: crochet/templates/crochet/pattern.html:163
|
||||||
#: crochet/templates/crochet/pattern.html:204
|
|
||||||
msgid "Vista previa"
|
msgid "Vista previa"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/account_home.html:48
|
#: crochet/templates/crochet/account_home.html:48
|
||||||
#: crochet/templates/crochet/pattern.html:50
|
#: crochet/templates/crochet/pattern.html:55
|
||||||
msgid "Eliminar"
|
msgid "Eliminar"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -91,16 +92,12 @@ msgstr ""
|
|||||||
|
|
||||||
#: crochet/templates/crochet/base.html:62
|
#: crochet/templates/crochet/base.html:62
|
||||||
#: crochet/templates/crochet/home.html:24
|
#: crochet/templates/crochet/home.html:24
|
||||||
|
#: crochet/templates/crochet/password_reset_complete.html:18
|
||||||
#: crochet/templates/registration/login.html:4
|
#: crochet/templates/registration/login.html:4
|
||||||
#: crochet/templates/registration/login.html:14
|
#: crochet/templates/registration/login.html:14
|
||||||
msgid "Iniciar sesión"
|
msgid "Iniciar sesión"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/base.html:63
|
|
||||||
#: crochet/templates/registration/register.html:29
|
|
||||||
msgid "Registrarme"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: crochet/templates/crochet/home.html:4
|
#: crochet/templates/crochet/home.html:4
|
||||||
msgid "Crochet — Crea y comparte tus patrones"
|
msgid "Crochet — Crea y comparte tus patrones"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -153,238 +150,327 @@ msgid ""
|
|||||||
"podrá editarlo."
|
"podrá editarlo."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:33
|
#: crochet/templates/crochet/password_reset_complete.html:4
|
||||||
|
#: crochet/templates/crochet/password_reset_complete.html:14
|
||||||
|
msgid "Contraseña actualizada"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_complete.html:16
|
||||||
|
msgid "Ya puedes iniciar sesión con tu nueva contraseña."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:4
|
||||||
|
msgid "Elegir nueva contraseña"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:15
|
||||||
|
msgid "Elige una contraseña nueva"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:33
|
||||||
|
msgid "Enlace no válido"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:35
|
||||||
|
msgid ""
|
||||||
|
"El enlace para restablecer la contraseña no es válido, puede que ya se haya "
|
||||||
|
"usado. Solicita uno nuevo."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_confirm.html:38
|
||||||
|
msgid "Solicitar un enlace nuevo"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_done.html:4
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:4
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:14
|
||||||
|
msgid "Recuperar contraseña"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_done.html:14
|
||||||
|
msgid "Revisa tu email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_done.html:16
|
||||||
|
msgid ""
|
||||||
|
"Si existe una cuenta con ese email, te hemos enviado un enlace para elegir "
|
||||||
|
"una contraseña nueva."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_done.html:19
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:32
|
||||||
|
msgid "Volver a iniciar sesión"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_email.html:2
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"Has recibido este email porque alguien ha solicitado restablecer la "
|
||||||
|
"contraseña de tu cuenta en %(site_name)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_email.html:4
|
||||||
|
msgid "Sigue este enlace para elegir una contraseña nueva:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_email.html:7
|
||||||
|
msgid "Tu usuario, por si lo has olvidado:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_email.html:9
|
||||||
|
msgid "Si no has solicitado este cambio, puedes ignorar este email."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:16
|
||||||
|
msgid ""
|
||||||
|
"Escribe tu email y te enviaremos un enlace para elegir una contraseña nueva."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_form.html:29
|
||||||
|
msgid "Enviar enlace"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/password_reset_subject.txt:1
|
||||||
|
#, python-format
|
||||||
|
msgid "Recupera tu contraseña en %(site_name)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/pattern.html:26
|
||||||
|
msgid "Idioma del patrón"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/crochet/pattern.html:38
|
||||||
msgid "No se ha podido guardar. Inténtalo de nuevo."
|
msgid "No se ha podido guardar. Inténtalo de nuevo."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:33
|
#: crochet/templates/crochet/pattern.html:38
|
||||||
msgid "Guardar"
|
msgid "Guardar"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:36
|
#: crochet/templates/crochet/pattern.html:41
|
||||||
msgid "Ver patrón"
|
msgid "Ver patrón"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:37
|
#: crochet/templates/crochet/pattern.html:42
|
||||||
msgid "Exportar a PDF"
|
msgid "Exportar a PDF"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:44
|
#: crochet/templates/crochet/pattern.html:49
|
||||||
msgid "Más opciones"
|
msgid "Más opciones"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:60
|
#: crochet/templates/crochet/pattern.html:65
|
||||||
msgid "Guardado"
|
msgid "Guardado"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:67
|
#: crochet/templates/crochet/pattern.html:72
|
||||||
msgid "Personalización de página"
|
msgid "Personalización de página"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:71
|
#: crochet/templates/crochet/pattern.html:76
|
||||||
msgid "Título del patrón"
|
msgid "Título del patrón"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:72
|
#: crochet/templates/crochet/pattern.html:77
|
||||||
msgid "Título del patrón..."
|
msgid "Título del patrón..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:75
|
#: crochet/templates/crochet/pattern.html:80
|
||||||
msgid "Autor"
|
msgid "Autor"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:76
|
#: crochet/templates/crochet/pattern.html:81
|
||||||
msgid "Autor..."
|
msgid "Autor..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:81
|
#: crochet/templates/crochet/pattern.html:86
|
||||||
msgid "Imagen de portada"
|
msgid "Imagen de portada"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:84
|
#: crochet/templates/crochet/pattern.html:89
|
||||||
msgid "No se ha podido subir la imagen de portada. Inténtalo de nuevo."
|
msgid "No se ha podido subir la imagen de portada. Inténtalo de nuevo."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:98
|
#: crochet/templates/crochet/pattern.html:103
|
||||||
#: crochet/templates/crochet/pattern.html:182
|
#: crochet/templates/crochet/pattern.html:187
|
||||||
msgid "Color del texto"
|
msgid "Color del texto"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:102
|
#: crochet/templates/crochet/pattern.html:107
|
||||||
msgid "Color de acento (títulos)"
|
msgid "Color de acento (títulos)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:106
|
#: crochet/templates/crochet/pattern.html:111
|
||||||
#: crochet/templates/crochet/pattern.html:182
|
#: crochet/templates/crochet/pattern.html:187
|
||||||
msgid "Color de fondo"
|
msgid "Color de fondo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:110
|
#: crochet/templates/crochet/pattern.html:115
|
||||||
msgid "Tipografía"
|
msgid "Tipografía"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:116
|
#: crochet/templates/crochet/pattern.html:121
|
||||||
msgid "Monoespaciada"
|
msgid "Monoespaciada"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:120
|
#: crochet/templates/crochet/pattern.html:125
|
||||||
msgid "Tamaño de letra"
|
msgid "Tamaño de letra"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:122
|
#: crochet/templates/crochet/pattern.html:127
|
||||||
msgid "Pequeño"
|
msgid "Pequeño"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:123
|
#: crochet/templates/crochet/pattern.html:128
|
||||||
msgid "Normal"
|
msgid "Normal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:124
|
#: crochet/templates/crochet/pattern.html:129
|
||||||
msgid "Grande"
|
msgid "Grande"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:128
|
#: crochet/templates/crochet/pattern.html:133
|
||||||
msgid "Alineación del texto"
|
msgid "Alineación del texto"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:130
|
#: crochet/templates/crochet/pattern.html:135
|
||||||
msgid "Izquierda"
|
msgid "Izquierda"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:131
|
#: crochet/templates/crochet/pattern.html:136
|
||||||
msgid "Centrado"
|
msgid "Centrado"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:132
|
#: crochet/templates/crochet/pattern.html:137
|
||||||
msgid "Justificado"
|
msgid "Justificado"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:136
|
#: crochet/templates/crochet/pattern.html:141
|
||||||
msgid "Tamaño de página"
|
msgid "Tamaño de página"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:141
|
#: crochet/templates/crochet/pattern.html:146
|
||||||
msgid "Carta (Letter)"
|
msgid "Carta (Letter)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:146
|
#: crochet/templates/crochet/pattern.html:151
|
||||||
msgid "Orientación"
|
msgid "Orientación"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:148
|
#: crochet/templates/crochet/pattern.html:153
|
||||||
msgid "Vertical"
|
msgid "Vertical"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:149
|
#: crochet/templates/crochet/pattern.html:154
|
||||||
msgid "Horizontal"
|
msgid "Horizontal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:157
|
#: crochet/templates/crochet/pattern.html:162
|
||||||
#: crochet/templates/crochet/pattern.html:165
|
#: crochet/templates/crochet/pattern.html:170
|
||||||
msgid "Secciones"
|
msgid "Secciones"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:167
|
#: crochet/templates/crochet/pattern.html:172
|
||||||
msgid "Colapsar todo"
|
msgid "Colapsar todo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:167
|
#: crochet/templates/crochet/pattern.html:172
|
||||||
msgid "Expandir todo"
|
msgid "Expandir todo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:172
|
#: crochet/templates/crochet/pattern.html:177
|
||||||
msgid "Añadir sección"
|
msgid "Añadir sección"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:175
|
#: crochet/templates/crochet/pattern.html:180
|
||||||
msgid "Título"
|
msgid "Título"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:175
|
#: crochet/templates/crochet/pattern.html:180
|
||||||
msgid "Título..."
|
msgid "Título..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:177
|
#: crochet/templates/crochet/pattern.html:182
|
||||||
msgid "Subtítulo"
|
msgid "Subtítulo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:177
|
#: crochet/templates/crochet/pattern.html:182
|
||||||
msgid "Subtítulo..."
|
msgid "Subtítulo..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:179
|
#: crochet/templates/crochet/pattern.html:184
|
||||||
msgid "Texto"
|
msgid "Texto"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:179
|
#: crochet/templates/crochet/pattern.html:184
|
||||||
msgid "Escribe aquí..."
|
msgid "Escribe aquí..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:181
|
#: crochet/templates/crochet/pattern.html:186
|
||||||
#: crochet/templates/crochet/pattern.html:182
|
#: crochet/templates/crochet/pattern.html:187
|
||||||
msgid "Nota"
|
msgid "Nota"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:181
|
#: crochet/templates/crochet/pattern.html:186
|
||||||
msgid "Escribe una nota o consejo..."
|
msgid "Escribe una nota o consejo..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:184
|
#: crochet/templates/crochet/pattern.html:189
|
||||||
msgid "Materiales"
|
msgid "Materiales"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:184
|
#: crochet/templates/crochet/pattern.html:189
|
||||||
msgid "Añadir material..."
|
msgid "Añadir material..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:184
|
#: crochet/templates/crochet/pattern.html:189
|
||||||
msgid "Añadir línea"
|
msgid "Añadir línea"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:186
|
#: crochet/templates/crochet/pattern.html:191
|
||||||
#: crochet/templates/crochet/pattern.html:188
|
#: crochet/templates/crochet/pattern.html:193
|
||||||
msgid "Imagen"
|
msgid "Imagen"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:188
|
#: crochet/templates/crochet/pattern.html:193
|
||||||
msgid "No se ha podido subir la imagen. Inténtalo de nuevo."
|
msgid "No se ha podido subir la imagen. Inténtalo de nuevo."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:190
|
#: crochet/templates/crochet/pattern.html:195
|
||||||
msgid "Patrón"
|
msgid "Patrón"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:190
|
#: crochet/templates/crochet/pattern.html:195
|
||||||
msgid "Elementos"
|
msgid "Elementos"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:192
|
#: crochet/templates/crochet/pattern.html:197
|
||||||
msgid "Grupo"
|
msgid "Grupo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:196
|
#: crochet/templates/crochet/pattern.html:201
|
||||||
msgid "Arrastrar para reordenar"
|
msgid "Arrastrar para reordenar"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:197
|
#: crochet/templates/crochet/pattern.html:202
|
||||||
msgid "Colapsar / expandir"
|
msgid "Colapsar / expandir"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:198
|
#: crochet/templates/crochet/pattern.html:203
|
||||||
msgid "Duplicar sección"
|
msgid "Duplicar sección"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:199
|
#: crochet/templates/crochet/pattern.html:204
|
||||||
msgid "Eliminar sección"
|
msgid "Eliminar sección"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:200
|
#: crochet/templates/crochet/pattern.html:205
|
||||||
msgid ""
|
msgid ""
|
||||||
"¿Seguro que quieres eliminar este grupo? Se eliminarán también todas las "
|
"¿Seguro que quieres eliminar este grupo? Se eliminarán también todas las "
|
||||||
"secciones que contiene."
|
"secciones que contiene."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/crochet/pattern.html:206
|
#: crochet/templates/crochet/pattern.html:210
|
||||||
msgid "Añade una sección para ver aquí el resultado."
|
msgid "Añade una sección para ver aquí el resultado."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -401,6 +487,10 @@ msgid "Entrar"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/registration/login.html:32
|
#: crochet/templates/registration/login.html:32
|
||||||
|
msgid "¿Has olvidado tu contraseña?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/registration/login.html:35
|
||||||
msgid "¿No tienes cuenta? Regístrate"
|
msgid "¿No tienes cuenta? Regístrate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -409,6 +499,10 @@ msgstr ""
|
|||||||
msgid "Crear cuenta"
|
msgid "Crear cuenta"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: crochet/templates/registration/register.html:29
|
||||||
|
msgid "Registrarme"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: crochet/templates/registration/register.html:32
|
#: crochet/templates/registration/register.html:32
|
||||||
msgid "¿Ya tienes cuenta? Inicia sesión"
|
msgid "¿Ya tienes cuenta? Inicia sesión"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -476,6 +570,22 @@ msgstr "cuenta/entrar/"
|
|||||||
msgid "account/logout/"
|
msgid "account/logout/"
|
||||||
msgstr "cuenta/salir/"
|
msgstr "cuenta/salir/"
|
||||||
|
|
||||||
|
#: crochet/urls.py:60
|
||||||
|
msgid "account/password-reset/"
|
||||||
|
msgstr "cuenta/recuperar-contrasena/"
|
||||||
|
|
||||||
|
#: crochet/urls.py:75
|
||||||
|
msgid "account/password-reset/done/"
|
||||||
|
msgstr "cuenta/recuperar-contrasena/enviado/"
|
||||||
|
|
||||||
|
#: crochet/urls.py:79
|
||||||
|
msgid "account/reset/<uidb64>/<token>/"
|
||||||
|
msgstr "cuenta/restablecer/<uidb64>/<token>/"
|
||||||
|
|
||||||
|
#: crochet/urls.py:87
|
||||||
|
msgid "account/reset/done/"
|
||||||
|
msgstr "cuenta/restablecer/hecho/"
|
||||||
|
|
||||||
#: crochet/views.py:24
|
#: crochet/views.py:24
|
||||||
msgid "Este patrón todavía no tiene contenido."
|
msgid "Este patrón todavía no tiene contenido."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{% extends 'crochet/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans 'Contraseña actualizada' %}{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
|
{% include 'crochet/_platform_assets.html' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main class="flex justify-center px-4 py-12">
|
||||||
|
<div class="card w-full max-w-sm bg-base-100 shadow-xl border border-base-300">
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="card-title">{% trans 'Contraseña actualizada' %}</h1>
|
||||||
|
<p class="text-sm text-base-content/70">
|
||||||
|
{% trans 'Ya puedes iniciar sesión con tu nueva contraseña.' %}
|
||||||
|
</p>
|
||||||
|
<a href="{% url 'crochet:login' %}" class="btn btn-primary mt-2">{% trans 'Iniciar sesión' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{% extends 'crochet/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans 'Elegir nueva contraseña' %}{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
|
{% include 'crochet/_platform_assets.html' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main class="flex justify-center px-4 py-12">
|
||||||
|
<div class="card w-full max-w-sm bg-base-100 shadow-xl border border-base-300">
|
||||||
|
<div class="card-body">
|
||||||
|
{% if validlink %}
|
||||||
|
<h1 class="card-title">{% trans 'Elige una contraseña nueva' %}</h1>
|
||||||
|
<form method="post" class="flex flex-col gap-3">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% for field in form %}
|
||||||
|
<label class="flex flex-col gap-1">
|
||||||
|
<span class="text-sm">{{ field.label }}</span>
|
||||||
|
{{ field }}
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<span class="text-error text-xs">{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
{% if field.help_text %}
|
||||||
|
<span class="text-xs text-base-content/60">{{ field.help_text }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
<button type="submit" class="btn btn-primary mt-2">{% trans 'Cambiar contraseña' %}</button>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<h1 class="card-title">{% trans 'Enlace no válido' %}</h1>
|
||||||
|
<p class="text-sm text-base-content/70">
|
||||||
|
{% trans 'El enlace para restablecer la contraseña no es válido, puede que ya se haya usado. Solicita uno nuevo.' %}
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-center mt-2">
|
||||||
|
<a href="{% url 'crochet:password_reset' %}" class="link link-primary">{% trans 'Solicitar un enlace nuevo' %}</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{% extends 'crochet/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans 'Recuperar contraseña' %}{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
|
{% include 'crochet/_platform_assets.html' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main class="flex justify-center px-4 py-12">
|
||||||
|
<div class="card w-full max-w-sm bg-base-100 shadow-xl border border-base-300">
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="card-title">{% trans 'Revisa tu email' %}</h1>
|
||||||
|
<p class="text-sm text-base-content/70">
|
||||||
|
{% trans 'Si existe una cuenta con ese email, te hemos enviado un enlace para elegir una contraseña nueva.' %}
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-center mt-2">
|
||||||
|
<a href="{% url 'crochet:login' %}" class="link link-primary">{% trans 'Volver a iniciar sesión' %}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{% load i18n %}{% autoescape off %}
|
||||||
|
{% blocktrans %}Has recibido este email porque alguien ha solicitado restablecer la contraseña de tu cuenta en {{ site_name }}.{% endblocktrans %}
|
||||||
|
|
||||||
|
{% trans 'Sigue este enlace para elegir una contraseña nueva:' %}
|
||||||
|
{{ protocol }}://{{ domain }}{% url 'crochet:password_reset_confirm' uidb64=uid token=token %}
|
||||||
|
|
||||||
|
{% trans 'Tu usuario, por si lo has olvidado:' %} {{ user.get_username }}
|
||||||
|
|
||||||
|
{% trans 'Si no has solicitado este cambio, puedes ignorar este email.' %}
|
||||||
|
{% endautoescape %}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{% extends 'crochet/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans 'Recuperar contraseña' %}{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
|
{% include 'crochet/_platform_assets.html' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main class="flex justify-center px-4 py-12">
|
||||||
|
<div class="card w-full max-w-sm bg-base-100 shadow-xl border border-base-300">
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="card-title">{% trans 'Recuperar contraseña' %}</h1>
|
||||||
|
<p class="text-sm text-base-content/70">
|
||||||
|
{% trans 'Escribe tu email y te enviaremos un enlace para elegir una contraseña nueva.' %}
|
||||||
|
</p>
|
||||||
|
<form method="post" class="flex flex-col gap-3">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% for field in form %}
|
||||||
|
<label class="flex flex-col gap-1">
|
||||||
|
<span class="text-sm">{{ field.label }}</span>
|
||||||
|
{{ field }}
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<span class="text-error text-xs">{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
<button type="submit" class="btn btn-primary mt-2">{% trans 'Enviar enlace' %}</button>
|
||||||
|
</form>
|
||||||
|
<p class="text-sm text-center mt-2">
|
||||||
|
<a href="{% url 'crochet:login' %}" class="link link-primary">{% trans 'Volver a iniciar sesión' %}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{% load i18n %}{% blocktrans %}Recupera tu contraseña en {{ site_name }}{% endblocktrans %}
|
||||||
@@ -29,6 +29,9 @@
|
|||||||
<button type="submit" class="btn btn-primary mt-2">{% trans 'Entrar' %}</button>
|
<button type="submit" class="btn btn-primary mt-2">{% trans 'Entrar' %}</button>
|
||||||
</form>
|
</form>
|
||||||
<p class="text-sm text-center mt-2">
|
<p class="text-sm text-center mt-2">
|
||||||
|
<a href="{% url 'crochet:password_reset' %}" class="link link-primary">{% trans '¿Has olvidado tu contraseña?' %}</a>
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-center">
|
||||||
<a href="{% url 'crochet:register' %}" class="link link-primary">{% trans '¿No tienes cuenta? Regístrate' %}</a>
|
<a href="{% url 'crochet:register' %}" class="link link-primary">{% trans '¿No tienes cuenta? Regístrate' %}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,17 +20,20 @@ class RegisterViewTests(TestCase):
|
|||||||
def test_post_creates_user_and_logs_in(self):
|
def test_post_creates_user_and_logs_in(self):
|
||||||
response = self.client.post(self.url, {
|
response = self.client.post(self.url, {
|
||||||
'username': 'crocheter',
|
'username': 'crocheter',
|
||||||
|
'email': 'crocheter@example.com',
|
||||||
'password1': 'a-very-uncommon-pw-1',
|
'password1': 'a-very-uncommon-pw-1',
|
||||||
'password2': 'a-very-uncommon-pw-1',
|
'password2': 'a-very-uncommon-pw-1',
|
||||||
})
|
})
|
||||||
|
|
||||||
self.assertTrue(User.objects.filter(username='crocheter').exists())
|
user = User.objects.get(username='crocheter')
|
||||||
|
self.assertEqual(user.email, 'crocheter@example.com')
|
||||||
self.assertRedirects(response, reverse('crochet:account_home'))
|
self.assertRedirects(response, reverse('crochet:account_home'))
|
||||||
self.assertIn('_auth_user_id', self.client.session)
|
self.assertIn('_auth_user_id', self.client.session)
|
||||||
|
|
||||||
def test_post_with_mismatched_passwords_does_not_create_user(self):
|
def test_post_with_mismatched_passwords_does_not_create_user(self):
|
||||||
response = self.client.post(self.url, {
|
response = self.client.post(self.url, {
|
||||||
'username': 'crocheter',
|
'username': 'crocheter',
|
||||||
|
'email': 'crocheter@example.com',
|
||||||
'password1': 'a-very-uncommon-pw-1',
|
'password1': 'a-very-uncommon-pw-1',
|
||||||
'password2': 'something-else',
|
'password2': 'something-else',
|
||||||
})
|
})
|
||||||
@@ -38,6 +41,18 @@ class RegisterViewTests(TestCase):
|
|||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertFalse(User.objects.filter(username='crocheter').exists())
|
self.assertFalse(User.objects.filter(username='crocheter').exists())
|
||||||
|
|
||||||
|
def test_post_without_email_does_not_create_user(self):
|
||||||
|
# Sin email no habría a dónde mandar el enlace de recuperación de
|
||||||
|
# contraseña (ver PasswordResetForm/StyledUserCreationForm).
|
||||||
|
response = self.client.post(self.url, {
|
||||||
|
'username': 'crocheter',
|
||||||
|
'password1': 'a-very-uncommon-pw-1',
|
||||||
|
'password2': 'a-very-uncommon-pw-1',
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertFalse(User.objects.filter(username='crocheter').exists())
|
||||||
|
|
||||||
|
|
||||||
class LoginViewTests(TestCase):
|
class LoginViewTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.contrib.auth.tokens import default_token_generator
|
||||||
|
from django.core import mail
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils import translation
|
||||||
|
from django.utils.encoding import force_bytes
|
||||||
|
from django.utils.http import urlsafe_base64_encode
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetRequestViewTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.user = User.objects.create_user(
|
||||||
|
username='crocheter', password='the-old-password-1', email='crocheter@example.com',
|
||||||
|
)
|
||||||
|
with translation.override('es'):
|
||||||
|
self.url = reverse('crochet:password_reset')
|
||||||
|
|
||||||
|
def test_get_renders_the_form(self):
|
||||||
|
response = self.client.get(self.url)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertTemplateUsed(response, 'crochet/password_reset_form.html')
|
||||||
|
|
||||||
|
def test_known_email_sends_a_reset_link(self):
|
||||||
|
response = self.client.post(self.url, {'email': 'crocheter@example.com'})
|
||||||
|
|
||||||
|
with translation.override('es'):
|
||||||
|
done_url = reverse('crochet:password_reset_done')
|
||||||
|
self.assertRedirects(response, done_url)
|
||||||
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
|
self.assertIn('crocheter@example.com', mail.outbox[0].to)
|
||||||
|
self.assertIn('http://testserver', mail.outbox[0].body)
|
||||||
|
|
||||||
|
def test_unknown_email_does_not_send_anything_but_still_redirects(self):
|
||||||
|
# Ni la vista ni la plantilla deben delatar si el email existe o no
|
||||||
|
# en el sistema (comportamiento por defecto de PasswordResetForm):
|
||||||
|
# misma redirección tanto si existe como si no, para no permitir
|
||||||
|
# enumerar cuentas registradas probando emails.
|
||||||
|
response = self.client.post(self.url, {'email': 'nobody@example.com'})
|
||||||
|
|
||||||
|
with translation.override('es'):
|
||||||
|
done_url = reverse('crochet:password_reset_done')
|
||||||
|
self.assertRedirects(response, done_url)
|
||||||
|
self.assertEqual(len(mail.outbox), 0)
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetDoneViewTests(TestCase):
|
||||||
|
def test_get_renders_the_confirmation_message(self):
|
||||||
|
with translation.override('es'):
|
||||||
|
url = reverse('crochet:password_reset_done')
|
||||||
|
response = self.client.get(url)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertTemplateUsed(response, 'crochet/password_reset_done.html')
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetConfirmViewTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.user = User.objects.create_user(
|
||||||
|
username='crocheter', password='the-old-password-1', email='crocheter@example.com',
|
||||||
|
)
|
||||||
|
uidb64 = urlsafe_base64_encode(force_bytes(self.user.pk))
|
||||||
|
token = default_token_generator.make_token(self.user)
|
||||||
|
with translation.override('es'):
|
||||||
|
self.confirm_url = reverse(
|
||||||
|
'crochet:password_reset_confirm', kwargs={'uidb64': uidb64, 'token': token},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_valid_link_allows_setting_a_new_password(self):
|
||||||
|
# PasswordResetConfirmView consume el token de la URL en el primer
|
||||||
|
# GET (redirige a una URL "set-password" en sesión) precisamente
|
||||||
|
# para que no quede reutilizable ni visible en el historial del
|
||||||
|
# navegador; hay que seguir esa redirección antes de poder enviar
|
||||||
|
# el formulario.
|
||||||
|
get_response = self.client.get(self.confirm_url, follow=True)
|
||||||
|
self.assertContains(get_response, 'id_new_password1')
|
||||||
|
|
||||||
|
response = self.client.post(get_response.redirect_chain[-1][0], {
|
||||||
|
'new_password1': 'the-new-password-2',
|
||||||
|
'new_password2': 'the-new-password-2',
|
||||||
|
})
|
||||||
|
|
||||||
|
with translation.override('es'):
|
||||||
|
complete_url = reverse('crochet:password_reset_complete')
|
||||||
|
self.assertRedirects(response, complete_url)
|
||||||
|
self.user.refresh_from_db()
|
||||||
|
self.assertTrue(self.user.check_password('the-new-password-2'))
|
||||||
|
|
||||||
|
def test_mismatched_passwords_do_not_change_the_password(self):
|
||||||
|
get_response = self.client.get(self.confirm_url, follow=True)
|
||||||
|
|
||||||
|
response = self.client.post(get_response.redirect_chain[-1][0], {
|
||||||
|
'new_password1': 'the-new-password-2',
|
||||||
|
'new_password2': 'something-else-3',
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, 'class="text-error text-xs"')
|
||||||
|
self.user.refresh_from_db()
|
||||||
|
self.assertTrue(self.user.check_password('the-old-password-1'))
|
||||||
|
|
||||||
|
def test_invalid_token_shows_the_invalid_link_message(self):
|
||||||
|
uidb64 = urlsafe_base64_encode(force_bytes(self.user.pk))
|
||||||
|
with translation.override('es'):
|
||||||
|
bogus_url = reverse(
|
||||||
|
'crochet:password_reset_confirm', kwargs={'uidb64': uidb64, 'token': 'not-a-real-token'},
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.client.get(bogus_url, follow=True)
|
||||||
|
|
||||||
|
self.assertContains(response, 'Enlace no válido')
|
||||||
|
self.assertNotContains(response, 'id_new_password1')
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetCompleteViewTests(TestCase):
|
||||||
|
def test_get_renders_the_success_message(self):
|
||||||
|
with translation.override('es'):
|
||||||
|
url = reverse('crochet:password_reset_complete')
|
||||||
|
response = self.client.get(url)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertTemplateUsed(response, 'crochet/password_reset_complete.html')
|
||||||
|
|
||||||
|
|
||||||
|
class LoginPageForgotPasswordLinkTests(TestCase):
|
||||||
|
def test_login_page_links_to_password_reset(self):
|
||||||
|
with translation.override('es'):
|
||||||
|
login_url = reverse('crochet:login')
|
||||||
|
reset_url = reverse('crochet:password_reset')
|
||||||
|
|
||||||
|
response = self.client.get(login_url)
|
||||||
|
|
||||||
|
self.assertContains(response, f'href="{reset_url}"')
|
||||||
+33
-2
@@ -1,8 +1,8 @@
|
|||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
from django.urls import path
|
from django.urls import path, reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from crochet.forms import StyledAuthenticationForm
|
from crochet.forms import StyledAuthenticationForm, StyledPasswordResetForm, StyledSetPasswordForm
|
||||||
from crochet.views import (
|
from crochet.views import (
|
||||||
AccountEmailUpdateView,
|
AccountEmailUpdateView,
|
||||||
AccountHomeView,
|
AccountHomeView,
|
||||||
@@ -56,4 +56,35 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
path(_('account/logout/'), name='logout', view=auth_views.LogoutView.as_view()),
|
path(_('account/logout/'), name='logout', view=auth_views.LogoutView.as_view()),
|
||||||
|
path(
|
||||||
|
_('account/password-reset/'), name='password_reset',
|
||||||
|
view=auth_views.PasswordResetView.as_view(
|
||||||
|
# No en registration/ (a diferencia de login.html/register.html):
|
||||||
|
# django.contrib.admin trae sus propias plantillas con estos
|
||||||
|
# mismos nombres bajo registration/ y, al ir antes que crochet
|
||||||
|
# en INSTALLED_APPS, el buscador de plantillas por APP_DIRS
|
||||||
|
# encontraría siempre las suyas primero, tapando las nuestras.
|
||||||
|
template_name='crochet/password_reset_form.html',
|
||||||
|
email_template_name='crochet/password_reset_email.html',
|
||||||
|
subject_template_name='crochet/password_reset_subject.txt',
|
||||||
|
form_class=StyledPasswordResetForm,
|
||||||
|
success_url=reverse_lazy('crochet:password_reset_done'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
_('account/password-reset/done/'), name='password_reset_done',
|
||||||
|
view=auth_views.PasswordResetDoneView.as_view(template_name='crochet/password_reset_done.html'),
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
_('account/reset/<uidb64>/<token>/'), name='password_reset_confirm',
|
||||||
|
view=auth_views.PasswordResetConfirmView.as_view(
|
||||||
|
template_name='crochet/password_reset_confirm.html',
|
||||||
|
form_class=StyledSetPasswordForm,
|
||||||
|
success_url=reverse_lazy('crochet:password_reset_complete'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
_('account/reset/done/'), name='password_reset_complete',
|
||||||
|
view=auth_views.PasswordResetCompleteView.as_view(template_name='crochet/password_reset_complete.html'),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user