I'm trying to reuse a code for registration form from my older project. The problem is that Django says that UserCreationForm hasn't attribute clean_password1.
Do you know where is the problem? I see that there is not such attribute in UserCreationForm but it worked before.
What should I do to make it work?
EDIT: It's because it calls super(...).clean_password1 which isn't in super class. So I've tried to put there super(...).cleaned_data.get("password1"), but it raises error that cleaned_data isn't there (in superclass).
class UserProfileCreationForm(UserCreationForm):
username = forms.CharField(label="Username", max_length=40, min_length=5)
email = forms.EmailField(label="Email address", max_length=40)
first_name = forms.CharField(label='First name', max_length=40, required=False)
last_name = forms.CharField(label='Last name', max_length=40, required=False)
password1 = forms.CharField(label="Password", widget=forms.PasswordInput, min_length=5)
password2 = forms.CharField(label="Password confirmation", widget=forms.PasswordInput)
class Meta():
model = UserProfile
fields = (
'username', 'email', 'type_of_user', 'first_name', 'last_name', 'password1', 'password2','IBAN',
)
def clean_password1(self):
password = self.cleaned_data.get('password1')
if len(password) < 8:
raise ValidationError('Password has to be of size at least 8 characters')
return super(UserProfileCreationForm, self).clean_password1()
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Password mismatch")
return password2
def save(self, commit=True):
try:
with transaction.atomic():
user = User(username=self.cleaned_data['username'],
first_name=self.cleaned_data['first_name'],
last_name=self.cleaned_data['last_name'],
email=self.cleaned_data['email'])
user.save()
user.set_password(self.cleaned_data["password1"])
user_profile = UserProfile(user=user,
IBAN=self.cleaned_data['IBAN'],
type_of_user=self.cleaned_data['type_of_user']
)
user_profile.save()
except:
raise #TODO: HANDLE THE EXCEPTION
return user
You can safely remove clean_password2 - Django already validates if the passwords match (I assume you're using the current version for your new project). As for clean_password1 I'd recommend to remove it too and read documentation on password validation (new in Django 1.9).
There's no reason to call super inside a clean_field method; the field doesn't exist on the base class, so neither does the clean_field.
Related
How to fix the error please help?Got AttributeError 'User' object has no attribute 'password1'.
i want to add two password fields. user is created but error occurs
AttributeError: Got AttributeError when attempting to get a value for field password1 on serializer UserSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the User instance.
Original exception text was: 'User' object has no attribute 'password1'.
views.py
class RegisterAPIView(generics.CreateAPIView):
serializer_class = UserSerializer
queryset = User.objects.all()
serializers.py
class UserSerializer(serializers.Serializer):
username = serializers.CharField(
label="Имя пользователя",
style={"input_type": "username"}
)
email = serializers.CharField(
label="почта",
style={"input_type": "email"}
)
password1 = serializers.CharField(
label="Пароль",
style={'input_type': 'password'}
)
password2 = serializers.CharField(
label="Пароль повторно",
style={'input_type': 'password'}
)
def create(self, validated_data):
password1 = validated_data.pop('password1')
password2 = validated_data.pop('password2')
print(validated_data)
if password1 and password2 and password1 != password2:
raise ValidationError("Passwords don't match")
validated_data["password"] = password1
print(validated_data)
user = User.objects.create(**validated_data)
print(user.id)
return user
For a Django project, I have a customized User model:
class User(AbstractUser):
username = None
email = models.EmailField(_('e-mail address'),
unique=True)
first_name = models.CharField(_('first name'),
max_length=150,
blank=False)
last_name = models.CharField(_('last name'),
max_length=150,
blank=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
objects = UserManager()
def __str__(self):
return self.email
I'm creating a new user registration form:
class UserRegistrationForm(forms.ModelForm):
auto_password = forms.BooleanField(label=_('Generate password and send by mail'),
required=False,
initial=True)
password = forms.CharField(label=_('Password'),
widget=forms.PasswordInput)
password2 = forms.CharField(label=_('Repeat password'),
widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'is_staff',
'is_superuser')
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError(_("Passwords don't match."))
return cd['password2']
My form has a auto_password boolean field. When this checkbox is set, the password and password2 fields must not be checked, as their content (or the absence of content) has no importance. On the opposite, when the auto_password checkbox is unset, the password and password2 must be checked.
Is there a way to optionnally disable the Django form checks whenever needed?
Thanks for the help.
You add this to the the condition in the clean method:
class UserRegistrationForm(forms.ModelForm):
auto_password = forms.BooleanField(
label=_('Generate password and send by mail'),
required=False,
initial=True
)
password = forms.CharField(
label=_('Password'),
widget=forms.PasswordInput
)
password2 = forms.CharField(
label=_('Repeat password'),
widget=forms.PasswordInput
)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'is_staff',
'is_superuser')
def clean(self):
data = super().clean()
if not data['auto_password'] and data['password'] != data['password2']:
raise forms.ValidationError(_('Passwords don't match.'))
return data
The not data['auto_password'] will thus return False in case the checkbox is checked, and in that case the the check of data['password'] != data['password2'] will not run, nor will it raise a ValidationError.
You can also remove the required=True properties, and check if the password contains at least one character by checking it truthiness:
class UserRegistrationForm(forms.ModelForm):
auto_password = forms.BooleanField(
label=_('Generate password and send by mail'),
# no required=True
initial=True
)
password = forms.CharField(
label=_('Password'),
widget=forms.PasswordInput
)
password2 = forms.CharField(
label=_('Repeat password'),
widget=forms.PasswordInput
)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'is_staff',
'is_superuser')
def clean(self):
data = super().clean()
manual = not data['auto_password']
if manual and not data['password']:
raise forms.ValidationError(_('Password is empty.'))
if manual and data['password'] != data['password2']:
raise forms.ValidationError(_('Passwords don't match.'))
return data
Can't you just include it in your logic?
if not cd['auto_password'] and (cd['password'] != cd['password2']):
raise forms.ValidationError(_("Passwords don't match."))
I am creating a form for a custom user type. But each time I submit the form to test it, it returns an error that says the unicode object has no attribute get error.
forms.py:
class RegistrationForm(forms.ModelForm):
"""
Form for registering a new account.
"""
password1 = forms.CharField(widget=forms.PasswordInput,
label="Password")
password2 = forms.CharField(widget=forms.PasswordInput,
label="Password (again)")
class Meta:
model = Student
fields = ('firstname', 'lastname', 'email', 'password1', 'password2', 'is_second_year')
def clean(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
models.py:
class StudentManager(BaseUserManager):
def create_user(self, firstname, lastname, email, is_second_year, password, is_officer=False, hours=0, points=0):
if not email:
raise ValueError("Student must have an email address.")
newStudent = self.model(
email = self.normalize_email(email),
firstname=firstname,
lastname=lastname,
is_officer=is_officer,
is_second_year=is_second_year,
hours=hours,
points=points
)
newStudent.set_password(password)
user.save(using=self.db)
return newStudent
def create_superuser(self, firstname, lastname, email, password, is_second_year, is_officer=True, hours=0, points=0):
newSuperStudent = self.create_user(
email = self.normalize_email(email),
firstname=firstname,
lastname=lastname,
is_officer=is_officer,
is_second_year=is_second_year,
hours=hours,
points=points,
password=password
)
newSuperStudent.is_admin = True
newSuperStudent.save(using=self.db)
return newSuperStudent
class Student(AbstractBaseUser):
firstname = models.CharField(verbose_name="First Name", max_length=30, default="")
lastname = models.CharField(verbose_name="Last Name", max_length=30, default="")
email = models.EmailField(
verbose_name='Email Address',
max_length=255,
unique=True,
default=''
)
is_officer = models.BooleanField(default=False)
is_second_year = models.BooleanField(verbose_name="Check this box if this is your second year in NHS")
hours = models.DecimalField(max_digits=5, decimal_places=2)
points = models.DecimalField(max_digits=3, decimal_places=1)
USERNAME_FIELD = 'email'
def __unicode__(self):
return self.username
views.py:
def sign_up(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = RegistrationForm(request.POST)
# check whether it's valid:
if form.is_valid():
print "money"
form.save()
# redirect to a new URL:
return HttpResponseRedirect('/sign_up_success/')
# if a GET (or any other method) we'll create a blank form
args = {}
args.update(csrf(request))
args['form'] = RegistrationForm()
return render_to_response('events/sign_up.html', args)
Error Location within the .is_valid() method:
field_value = self.cleaned_data.get(field, None)
My guess is that for some reason, the cleaned_data attribute of my form is a unicode object rather than a dictionary. But I have no clue why this is so!
clean must return the full cleaned_data dictionary, not a single string field.
I am using Django 1.8.After following tutorials of how to customize user model I decided to make an app using customized user model. My CustomUser model looks like -
class CustomUser(AbstractBaseUser):
first_name = models.CharField(max_length=100,blank=True)
last_name = models.CharField(max_length=100,blank=True)
college = models.CharField(max_length=200,blank=True)
email = models.EmailField(unique=True,blank=False)
date_joined = models.DateTimeField(_('date joined'), default=datetime.now())
is_active = models.BooleanField(default=True)
is_superuser = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name']
objects = CustomUserManager()
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_absolute_url(self):
return "/users/%s/" % urlquote(self.email)
def get_full_name(self):
"""
Returns the first name plus the last name , with a space in between
"""
full_name = '%s %s' % (self.first_name,self.last_name)
return full_name.strip()
My CustomUserManager class is this (though not important to mention here) -
class CustomUserManager(BaseUserManager):
def _create_user(self,email,password,is_staff,is_superuser,**extra_fields):
"""
Creates and saves a User with the given email and password
"""
t = datetime.now()
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email,is_staff=is_staff,is_active=True,is_superuser=is_superuser,
last_login=t,date_joined=t,**extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self,email,password=None,**extra_fields):
return self._create_user(email,password,False,False,**extra_fields)
def create_superuser(self,email,password=None,**extra_fields):
print "Inside Superuser"
return self._create_user(email,password,True,True,**extra_fields)
I have added the relevant settings - AUTH_USER_MODEL and AUTHENTICATION_BACKENDS to the settings.py file.
Most importantly my custom registration form looks like this -
class CustomUserCreationForm(UserCreationForm):
"""
A form that creates a user, with no privileges, from the given email and password
"""
def __init__(self,*args,**kargs):
super(CustomUserCreationForm,self).__init__(*args,**kargs)
#print self.fields
del self.fields['username']
class Meta:
model = CustomUser
fields = ('email',)
I have mentioned here that my model will be CustomUser.As you can see that my custom form inherits from in-built UserCreation form. For the convenience I am also posting here UserCreationFrom class -
class UserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username and
password.
"""
error_messages = {
'password_mismatch': _("The two password fields didn't match."),
}
password1 = forms.CharField(label=_("Password"),
widget=forms.PasswordInput)
password2 = forms.CharField(label=_("Password confirmation"),
widget=forms.PasswordInput,
help_text=_("Enter the same password as above, for verification."))
class Meta:
model = User
fields = ("username",)
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
I have some doubts here.UserCreationForm has model set to User which is default User model(from django.contrib.auth.models import User);
but in my CustomForm's meta class I have mentioned model equal to my CustomUser.
When I print the fields returned by UserCreationForm it gives - username,password1,password2.Presence of 'username' field is the proof that UserCreationForm used 'User' model and added 'username' field which subsequently I deleted in my custom form.
I have also added 'email' to the fields in my custom form but Email option is not rendering in my registration page.Is what I am doing the right way to create Custom Registration forms?
If not then what should be done to render email field in my custom registration form.
from .models import CustomUser
class UserCreationForm(forms.ModelForm):
password1 = forms.CharField(label="Password", widget=forms.PasswordInput)
password2 = forms.CharField(label="Password confirmation", widget=forms.PasswordInput)
class Meta:
model = CustomUserModel
# Note - include all *required* CustomUser fields here,
# but don't need to include password1 and password2 as they are
# already included since they are defined above.
fields = ("email",)
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
msg = "Passwords don't match"
raise forms.ValidationError("Password mismatch")
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
Source:
Django 1.5: UserCreationForm & Custom Auth Model
I am using Django 1.3/Python 2.7.
My application is using django.contrib.auth for User management. For the main user registration I have a form which checks if the 'email' has already been registered. So it makes sure all email fields are unique.
But it happens that some admins use the django admin interface to add users, and end up adding duplicate accounts with the same email.
For this purpose I have created a NewUserCreationForm, where I've duplicated the django.contrib.auth.UserCreationForm and added an 'email' field to it.
class NewUserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username and password.
"""
username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^[\w.#+-]+$',
help_text = _("Required. 30 characters or fewer. Letters, digits and #/./+/-/_ only."),
error_messages = {'invalid': _("This value may contain only letters, numbers and #/./+/-/_ characters.")})
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput,
help_text = _("Enter the same password as above, for verification."))
email = forms.EmailField(label=_("Email"), max_length=75)
class Meta:
model = User
fields = ("username", "email")
def clean_username(self):
username = self.cleaned_data["username"]
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(_("A user with that username already exists."))
def clean_password2(self):
password1 = self.cleaned_data.get("password1", "")
password2 = self.cleaned_data["password2"]
if password1 != password2:
raise forms.ValidationError(_("The two password fields didn't match."))
return password2
def save(self, commit=True):
user = super(NewUserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.email = self.email
if commit:
user.save()
return user
class CustomUserAdmin(UserAdmin):
add_form = NewUserCreationForm
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
But this code isn't working. I can see the form rendering, but with no email field, just the Username, password1 and password2 fields.
what is it that I am missing here?
You are missing ... UserAdmin.add_fieldsets, e.g.:
class CustomUserAdmin(UserAdmin):
add_form = NewUserCreationForm
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2', 'email')}
),
)