I'm upgrading a Django 3.0 app to 5.1 and have been moving slowly through each minor release. So far so good. However, once I went from Django 5.0 to 5.1, I saw changed behavior with my "Create New User" page which uses a UserCreationForm form that allows empty passwords. If no password is supplied, a random one is generated. Now, if I submit the form with an empty password I get "required field" errors on the password fields, even though they are both explicitly set as required=False. I saw there were UserCreationForm changes in Django 5.1.0 and 5.1.1. I tried using AdminUserCreationForm and setting the usable_password field to None, but it still won't allow empty passwords like before. Any ideas? Environment Python 3.12.8 Django 5.1.5 Crispy Forms 2.3 Simplified Code from django.contrib.auth.forms import AdminUserCreationForm from crispy_forms.helper import FormHelper class SignupForm(AdminUserCreationForm): # previously using UserCreationForm usable_password = None # Newly added # Form fields sharedaccountflag = forms.ChoiceField( label = 'Cuenta compartida', required = True ) # Constructor def __init__(self, *args, **kwargs): # Call base class constructor super(SignupForm, self).__init__(*args, **kwargs) # Set password fields as optional self.fields['password1'].required = False self.fields['password2'].required = False # Set form helper properties self.helper = FormHelper() self.helper.form_tag = False # Specify model and which fields to include in form class Meta: model = get_user_model() fields = ('password1', 'password2', 'sharedaccountflag')  Screenshot   Update I used Serhii's example and modified it so the normal validation is called when appropriate. I also changed back to use UserCreationForm: class SignupForm(UserCreationForm): # Override default validation to allow empty password (change in Django 5.1) def validate_passwords( self, password1_field_name = "password1", password2_field_name = "password2" ): # Store password values password1 = self.cleaned_data.get(password1_field_name) password2 = self.cleaned_data.get(password2_field_name) # Do nothing if passwords are not required and no value is provided if ( not self.fields[password1_field_name].required and not self.fields[password2_field_name].required and not password1.strip() and not password2.strip() ): pass # Call default validation if password is required OR a value is provided else: super().validate_passwords(password1_field_name, password2_field_name) 
Yes. In new versions of Django, the source code has changed and the behaviour of the BaseUserCreationForm class has changed accordingly. The password1 and password2 fields are now created using the static method SetPasswordMixin.create_password_fields(), and they default to required=False. This can be easily checked here. But even though the fields are optional, the validate_passwords method is always called, in the clean method and checks that the fields are not empty. For example, when you call something like this form.is_valid(), clean will be called. If you need behaviour where empty passwords are allowed, given required=False you can define a custom validate_passwords method like the one in the code below, this will allow you to create users with empty passwords: from django.contrib.auth import forms class CustomUserCreationForm(forms.UserCreationForm): def validate_passwords( self, password1_field_name: str = "password1", password2_field_name: str = "password2"): def is_password_field_required_and_not_valid(field_name: str) -> bool: is_required = self.fields[field_name].required cleaned_value = self.cleaned_data.get(field_name) is_field_has_errors = field_name in self.errors return ( is_required and not cleaned_value and not is_field_has_errors ) if is_password_field_required_and_not_valid(password1_field_name): error = ValidationError( self.fields[password1_field_name].error_messages["required"], code="required", ) self.add_error(password1_field_name, error) if is_password_field_required_and_not_valid(password2_field_name): error = ValidationError( self.fields[password2_field_name].error_messages["required"], code="required", ) self.add_error(password2_field_name, error) password1 = self.cleaned_data.get(password1_field_name) password2 = self.cleaned_data.get(password2_field_name) if password1 != password2: error = ValidationError( self.error_messages["password_mismatch"], code="password_mismatch", ) self.add_error(password2_field_name, error)  p.s. I'm not sure if that's the way it was intended, maybe there's just a mistake made, in validate_passwords, where the required flag is simply not taken into account.