1

Is it possible to enforce a minimum password length if you're using Django 1.8 or under when a user is changing their password? When a user creates their account in my website, I enforce a minimum password length using a custom validator in my signup form. However, when a user wants to change their password, I call Django's auth_views.password_change method which specifies the form and validation criteria used.

# account/urls.py
from django.conf.urls import url
from django.contrib.auth import views as auth_views
urlpatterns = [
    ...
    url(r'^password_change/$',
        auth_views.password_change,
        {'template_name': 'password_change_form.html'},
        name='password_change'),
    ...
]

Since I'm not validating their new password, users will be able to change it to one that doesn't meet my minimum length criteria. Is there any way to do this validation other than monkey-patching? This Stackover question discusses an approach that works, but it's for the situation where you're implementing authentication whereas I'm only allowing an authenticated user to change their existing password. I know Django 1.9 will provide this ability via an AUTH_PASSWORD_VALIDATORS setting but I won't have time to upgrade to 1.9 before my site goes live.

Community
  • 1
  • 1
Jim
  • 13,430
  • 26
  • 104
  • 155
  • You can make a new form that inherit from from `PasswordChangeForm`, customize 'new_password1' field with `clean_new_password1`(add your validation), and also add `{'password_change_form': CustomPasswordChangeForm},` in your **url** to render this form rather the default one. You can use view if you want, see [here](http://stackoverflow.com/questions/26457279/passwordchangeform-with-custom-user-model), if it could help – kapilsdv Jul 15 '16 at 17:31

1 Answers1

1

You can customize the default PasswordChangeForm form and pass password_change_form extra options to view functions through url to point to your CustomPasswordChangeForm form rather the default one.

from django.contrib.auth.forms import PasswordChangeForm


class CustomPasswordChangeForm(PasswordChangeForm):
    """
    A Custom PasswordChangeForm for minimum password length validation.
    """

    def clean_new_password1(self):
        """
        Validates that the new_password1.
        """
        password = self.cleaned_data.get('new_password1')
        # Add your custom validation
        if len(password) < 8:
            raise ValidationError('Password too short')
        return password

And change the url:

from django.conf.urls import url
from django.contrib.auth import views as auth_views
from _where_ import CustomPasswordChangeForm #import the CustomPasswordChangeFormform 

urlpatterns = [
    ...
    url(r'^password_change/$',
        auth_views.password_change,
        {'template_name': 'password_change_form.html', 'password_change_form': CustomPasswordChangeForm},
        name='password_change'),
    ...
]
kapilsdv
  • 719
  • 4
  • 10
  • This almost works. It does catch a password that's too short but if you then enter a valid password and re-submit the form, an AttributeError is raised, "'super' object has no attribute 'clean_new_password1'". I ran this in the debugger and confirmed there's no such method. Did you perhaps mean something else? I was wondering if you really meant "super(CustomPasswordChangeForm,..)" but that raises the same error. – Jim Jul 16 '16 at 21:49
  • I didn't test it. It was just coded in fly. Also `'super'(PasswordChangeForm) object has no attribute 'clean_new_password1'` , its the `self`(CustomPasswordChangeForm) that has it. Use `return password` instead of `super(..)` – kapilsdv Jul 17 '16 at 05:21
  • Thanks for the advice regarding hidden fields. I've changed my code appropriately. – Jim Jul 19 '16 at 17:07