11from django .contrib .auth .models import Group
2- from django .contrib .auth .forms import UserChangeForm , UserCreationForm
2+ from django .contrib .auth .forms import UserCreationForm
33from django .utils .translation import gettext_lazy as _
44from django import forms
55from modeltranslation .forms import TranslationModelForm
@@ -19,17 +19,15 @@ def clean_identifier(self):
1919 return self .cleaned_data ["identifier" ]
2020
2121
22- class UserCreationForm (UserCreationForm ):
23- is_superuser = forms . BooleanField ( required = False , label = _ ( "Administrator" ))
22+ class UserForm (UserCreationForm ):
23+ """Form used for user creation and edit.
2424
25- def __init__ (self , * args , ** kwargs ):
26- super (UserCreationForm , self ).__init__ (* args , ** kwargs )
27- self .fields ["groups" ] = forms .MultipleChoiceField (
28- choices = Group .objects .all ().values_list ("id" , "name" ),
29- required = False ,
30- label = _ ("Groups" ),
31- help_text = _ ("Ctrl + Click to select multiple or unselect." ),
32- )
25+ It uses UserCreationForm as base for both cases to allow editing the user
26+ password on edit. The password fields are required on creation but not on
27+ edit, when the password will only be updated if the fields are populated.
28+ """
29+
30+ is_superuser = forms .BooleanField (required = False , label = _ ("Administrator" ))
3331
3432 class Meta :
3533 model = User
@@ -41,56 +39,29 @@ class Meta:
4139 "is_active" ,
4240 "is_superuser" ,
4341 "groups" ,
42+ "password1" ,
43+ "password2" ,
4444 )
4545
46-
47- class UserChangeForm (UserChangeForm ):
48- password = forms .CharField (widget = forms .PasswordInput , required = False )
49- password_confirmation = forms .CharField (widget = forms .PasswordInput , required = False )
50- is_superuser = forms .BooleanField (required = False , label = _ ("Administrator" ))
51-
5246 def __init__ (self , * args , ** kwargs ):
53- super (UserChangeForm , self ).__init__ (* args , ** kwargs )
47+ super ().__init__ (* args , ** kwargs )
5448 self .fields ["groups" ] = forms .MultipleChoiceField (
5549 choices = Group .objects .all ().values_list ("id" , "name" ),
5650 required = False ,
5751 label = _ ("Groups" ),
5852 help_text = _ ("Ctrl + Click to select multiple or unselect." ),
5953 )
60-
61- class Meta :
62- model = User
63- fields = (
64- "username" ,
65- "first_name" ,
66- "last_name" ,
67- "email" ,
68- "is_active" ,
69- "is_superuser" ,
70- "groups" ,
71- )
72-
73- def clean_password (self ):
74- password = self .cleaned_data .get ("password" , "" )
75- if password != "" and len (password ) < 8 :
76- raise forms .ValidationError (
77- _ ("Password should be at least 8 characters long" )
78- )
79- return password
80-
81- def clean (self ):
82- super (UserChangeForm , self ).clean ()
83- password = self .cleaned_data .get ("password" , "" )
84- password_conf = self .cleaned_data .get ("password_confirmation" , "" )
85- if password != password_conf :
86- raise forms .ValidationError (
87- _ ("Password and password confirmation do not match" )
88- )
89- return self .cleaned_data
54+ # Password fields are not required when editing
55+ if "instance" in kwargs :
56+ self .fields ["password1" ].required = False
57+ self .fields ["password2" ].required = False
9058
9159 def save (self ):
92- user = super (UserChangeForm , self ).save (commit = False )
93- password = self .cleaned_data .get ("password" , "" )
60+ # Call ModelForm save directly to avoid setting the
61+ # user password allways in UserCreationForm save.
62+ user = super (UserCreationForm , self ).save (commit = False )
63+ # Only set the password when it's populated. It's required on creation.
64+ password = self .cleaned_data .get ("password1" , "" )
9465 if password != "" :
9566 user .set_password (password )
9667 user .save ()
0 commit comments