Reputation: 110432
I am currently using django.contrib.auth.views.password_password_reset_confirm
to change a user's password. This is how my urls look:
from django.contrib.auth import views as auth_views
url(r'^password/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
redirect_if_loggedin(auth_views.password_reset_confirm),
name='auth_password_reset_confirm'),
Currently, I am doing it directly into the django trunk -
# django.contrib.auth.views
def clean_new_password2(self):
password1 = self.cleaned_data.get('new_password1')
password2 = self.cleaned_data.get('new_password2')
if password1 and password2:
if len(password1) < 8:
raise forms.ValidationError(_("Password must be at least 8 chars."))
if password1 != password2:
raise forms.ValidationError(_("The two password fields didn't match."))
return password2
Surely there must be a better way.
Upvotes: 7
Views: 5162
Reputation: 17385
The code that I eventually wrote after understanding Arthur's accepted answer:
This is the inherited form:
class SetPasswordWithMinLengthForm(SetPasswordForm):
"""
Inherited form that lets a user change set his/her password without
entering the old password while validating min password length
"""
def clean_new_password1(self):
password1 = self.cleaned_data.get('new_password1')
if len(password1) < 4:
raise ValidationError("Password must be at least 4 chars.")
return password1
In the urls.py
you can instruct the view to use the custom form by specifing set_password_form
:
url(r'^forgot_password/reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
{'set_password_form':SetPasswordWithMinLengthForm}),
Upvotes: 6
Reputation: 622
I'm using the django-registration plugin, which I've found to be excellent, so my example is based on that. But you could do a very similar thing without it.
This post does a good job of walking one through how to override a form (and widget) for django-registration -- in this case for a recaptcha spam-bot blocker.
What you need to do is override the RegistrationForm class (as below) and point your urls.py to use it instead of the default RegistrationForm
class MinPasswdLenRegistrationForm(RegistrationForm):
min_password_length = 8
def clean_password1(self):
" Minimum length "
password1 = self.cleaned_data.get('password1', '')
if len(password1) < self.min_password_length:
raise forms.ValidationError("Password must have at least %i characters" % self.min_password_length)
else:
return password1
(In a Form class, django will look for functions that start with clean_
and end with a field name (like password1
) to execute during form validation.)
The other important bit is to use the form in your urls.py, like so:
from django.conf.urls.defaults import *
from registration.views import register
from myapp.forms import MinPasswdLenRegistrationForm
urlpatterns = patterns('',
url(r'^register/$', register,
{'form_class': MinPasswdLenRegistrationForm},
name='registration.views.register'),
(r'', include('registration.urls')),
)
HTH
Upvotes: 4
Reputation: 1984
If I understand correctly, you're modifying the django code? Because that's just can not be the way to do it.
What form do you use? It seems indeed that the built-in PasswordChangeForm won't let you set a min_length.
Maybe you could use the password_change view and set your own password_change_form, which could inherit from the basic PasswordChangeForm to which you could apply additional cleaning.
Upvotes: 2