python - logoutview - password django
check_password() de un usuario otra vez (3)
Gracias de nuevo a Yuji. Funciona cuando no tengo en mi primera def __init__
la variable usuario. También agregué en def clean_password
las primeras 2 líneas del def clean_email
from django import forms
from django.db.models.loading import cache
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
class EmailChangeForm(forms.Form):
email = forms.EmailField(label=''New E-mail'', max_length=75)
password = forms.CharField(widget=forms.PasswordInput)
def __init__(self, *args, **kwargs):
self.user = user
super(EmailChangeForm, self).__init__(*args, **kwargs)
def clean_password(self):
User = cache.get_model(''auth'', ''User'')
user = User.objects.get(username__exact=self.username)
valid = user.check_password(self.cleaned_data[''password''])
if not valid:
raise forms.ValidationError("Password Incorrect")
return valid
def __init__(self, username=None, *args, **kwargs):
"""Constructor.
**Mandatory arguments**
``username``
The username of the user that requested the email change.
"""
self.username = username
super(EmailChangeForm, self).__init__(*args, **kwargs)
def clean_email(self):
"""Checks whether the new email address differs from the user''s current
email address.
"""
email = self.cleaned_data.get(''email'')
User = cache.get_model(''auth'', ''User'')
user = User.objects.get(username__exact=self.username)
# Check if the new email address differs from the current email address.
if user.email == email:
raise forms.ValidationError(''New email address cannot be the same /
as your current email address'')
return email
Tengo el siguiente formulario. ¿Cómo puedo verificar la contraseña del usuario nuevamente, antes de que el usuario pueda cambiar su emailadsress finalmente? Incluso él está conectado, solo quiero estar seguro de que realmente es el usuario. Sólo una cosa segura.
¿Cómo lo hago con .check_password()
?
''EmailChangeForm'' object has no attribute ''user''
/home/craphunter/workspace/project/trunk/project/auth/user/email_change/forms.py in clean_password, line 43
from django import forms
from django.db.models.loading import cache
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
class EmailChangeForm(forms.Form):
email = forms.EmailField(label=''New E-mail'', max_length=75)
password = forms.CharField(widget=forms.PasswordInput)
def __init__(self, user, *args, **kwargs):
super(EmailChangeForm, self).__init__(*args, **kwargs)
self.user = user
def clean_password(self):
valid = self.user.check_password(self.cleaned_data[''password''])
if not valid:
raise forms.ValidationError("Password Incorrect")
return valid
def __init__(self, username=None, *args, **kwargs):
"""Constructor.
**Mandatory arguments**
``username``
The username of the user that requested the email change.
"""
self.username = username
super(EmailChangeForm, self).__init__(*args, **kwargs)
def clean_email(self):
"""Checks whether the new email address differs from the user''s current
email address.
"""
email = self.cleaned_data.get(''email'')
User = cache.get_model(''auth'', ''User'')
user = User.objects.get(username__exact=self.username)
# Check if the new email address differs from the current email address.
if user.email == email:
raise forms.ValidationError(''New email address cannot be the same /
as your current email address'')
return email
Me gustaría refactorizar su código para ver algo como esto:
Ver:
@login_required
def view(request, extra_context=None, ...):
form = EmailChangeForm(user=request.user, data=request.POST or None)
if request.POST and form.is_valid():
send_email_change_request(request.user,
form.cleaned_data[''email''],
https=request.is_secure())
return redirect(success_url)
...
La validación de la contraseña pasa a formar:
class EmailChangeForm(Form):
email = ...
old_password = CharField(..., widget=Password())
def __init__(self, user, data=None):
self.user = user
super(EmailChangeForm, self).__init__(data=data)
def clean_old_password(self):
password = self.cleaned_data.get(''password'', None)
if not self.user.check_password(password):
raise ValidationError(''Invalid password'')
Extraer la lógica de la vista:
def send_email_change_request(user, new_email, https=True):
site = cache.get_model(''sites'', ''Site'')
email = new_email
verification_key = generate_key(user, email)
current_site = Site.objects.get_current()
site_name = current_site.name
domain = current_site.domain
protocol = ''https'' if https else ''http''
# First clean all email change requests made by this user
qs = EmailChangeRequest.objects.filter(user=request.user)
qs.delete()
# Create an email change request
change_request = EmailChangeRequest(
user = request.user,
verification_key = verification_key,
email = email
)
change_request.save()
# Prepare context
c = {
''email'': email,
''site_domain'': ''dev.tolisto.de'',
''site_name'': ''tolisto'',
''user'': self.user,
''verification_key'': verification_key,
''protocol'': protocol,
}
c.update(extra_context)
context = Context(c)
# Send success email
subject = "Subject" # I don''t think that using template for
# subject is good idea
message = render_to_string(email_message_template_name, context_instance=context)
send_mail(subject, message, None, [email])
No coloque cosas complicadas dentro de las vistas (como renderizar y enviar correos electrónicos).
Siento que respondiste tu propia pregunta:)
Los documentos sobre el método check_password
están aquí: http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.models.User.check_password
success = user.check_password(request.POST[''submitted_password''])
if success:
# do your email changing magic
else:
return http.HttpResponse("Your password is incorrect")
# or more appropriately your template with errors
Ya que está pasando la solicitud. Usuario a su constructor de formularios (parece que ha __init__
por sus propias razones), podría poner toda su lógica en el formulario sin ningún problema.
class MyForm(forms.Form):
# ...
password = forms.CharField(widget=forms.PasswordInput)
def __init__(self, user, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.user = user
def clean_password(self):
valid = self.user.check_password(self.cleaned_data[''password''])
if not valid:
raise forms.ValidationError("Password Incorrect")
return valid
actualizar despues de ver tus formularios
DE ACUERDO. El problema principal es que __init__
se ha definido dos veces, haciendo inútil la primera declaración. El segundo problema que veo es que estaríamos haciendo múltiples consultas para el user
cuando realmente no tenemos que hacerlo.
Nos hemos alejado bastante de tu pregunta original, pero espero que esta sea una experiencia de aprendizaje.
He cambiado sólo algunas cosas:
- Se eliminó la definición extra de
__init__
- Se cambió
__init__
para aceptar una instancia deUser
lugar de unusername
texto - Se eliminó la consulta de
User.objects.get(username=username)
ya que estamos pasando un objeto de usuario.
Solo recuerde pasar el constructor de formulario user=request.user
lugar de username=request.user.username
class EmailChangeForm(forms.Form):
email = forms.EmailField(label=''New E-mail'', max_length=75)
password = forms.CharField(widget=forms.PasswordInput)
def __init__(self, user=None, *args, **kwargs):
self.user = user
super(EmailChangeForm, self).__init__(*args, **kwargs)
def clean_password(self):
valid = self.user.check_password(self.cleaned_data[''password''])
if not valid:
raise forms.ValidationError("Password Incorrect")
def clean_email(self):
email = self.cleaned_data.get(''email'')
# no need to query a user object if we''re passing it in anyways.
user = self.user
# Check if the new email address differs from the current email address.
if user.email == email:
raise forms.ValidationError(''New email address cannot be the same /
as your current email address'')
return email
Finalmente, ya que estamos hablando de buenas prácticas aquí, recomiendo seguir con las sugerencias de Skirmantas sobre cómo mover su código de vista actual a un método de formulario para que pueda llamar a myform.send_confirmation_email
.
¡Suena como un buen ejercicio!