I am trying to setup the SetPasswordForm on Django, but I get the following error when trying to put in a new password: 'SetPasswordForm' object has no attribute ‘save’.
Would anyone know how to configure this properly? Thank you in advance!
forms.py:
class SetPasswordForm(forms.Form):
password1 = forms.CharField(label='New password',
widget=forms.PasswordInput(
attrs={'placeholder': 'New password'}))
password2 = forms.CharField(label='Verify',
widget=forms.PasswordInput(
attrs={'placeholder': 'Password again'}))
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(SetPasswordForm, self).__init__(*args, **kwargs)
def clean_password2(self):
password_length = settings.MIN_PASSWORD_LENGTH
password1 = self.cleaned_data.get("password1")
if len(password1) < password_length:
raise forms.ValidationError(
"Password must be longer than "
"{} characters".format(password_length))
password2 = self.cleaned_data.get("password2")
if password1 and password2:
if password1 != password2:
raise forms.ValidationError("Passwords do not match")
return password2
views.py:
#sensitive_post_parameters()
#never_cache
def password_reset_confirm(request, uidb64=None, token=None,
token_generator=default_token_generator):
assert uidb64 is not None and token is not None
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = MyUser._default_manager.get(pk=uid)
except (TypeError, ValueError, OverflowError, MyUser.DoesNotExist):
user = None
if user is not None and token_generator.check_token(user, token):
validlink = True
form = SetPasswordForm(request.POST or None, user=user)
if request.method == 'POST':
if form.is_valid():
form.save() # Error traces back to here
return HttpResponseRedirect(render("login"))
else:
validlink = False
form = None
messages.error(request, "Password reset unsuccessful")
context = {
'form': form,
'validlink': validlink
}
return render(request, 'accounts/settings/password_set.html', context)
I just needed to add the following to my form:
def save(self, commit=True):
self.user.set_password(self.cleaned_data['password2'])
if commit:
self.user.save()
return self.user
Related
I'm trying to make a Login but it doesn't work.
the error is
form.is_valid() return False and
'LoginForm' object has no attribute 'cleaned_data'
I can't figure out out is the problem.
user/forms.py
class LoginForm(forms.Form):
email = forms.EmailField(widget=forms.EmailInput(
attrs={'style': 'width:100%; height:100%;'}))
password = forms.CharField(widget=forms.PasswordInput(
attrs={'style': 'width:100%; height:100%;'}))
def __init__(self, request=None, *args, **kwargs):
self.request = request
super(LoginForm, self).__init__(*args, **kwargs)
self.fields['email'].label = "이메일"
self.fields['password'].label = "비밀번호"
def clean(self):
super().clean()
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
try:
user = models.User.objects.get(email=email)
if user.check_password(password):
return self.cleaned_data
else:
self.add_error("password", forms.ValidationError(
"비밀번호가 틀렸습니다."))
except models.User.DoesNotExist:
self.add_error("email", forms.ValidationError(
"존재하지 않는 계정입니다."))
users/views.py
class LoginView(mixins.LoggedOutOnlyView, View):
def get(self, request):
form = forms.LoginForm(request.POST)
return render(request, "users/login.html", {"form": form})
def post(self, request):
form = forms.LoginForm(request.POST or None)
print(form.is_valid())
if form.is_valid():
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
get_user_name = user_models.User.objects.get(email=email)
user = authenticate(
request, username=get_user_name, password=password)
if user is not None:
login(request, user)
return redirect(reverse("cores:home"))
else:
return render(request, "users/login.html", {"form": form})
You need to set a local variable with the return value of the super() call. In your fields you'd no longer call the self.cleaned_data variant but the local variable cleaned_data. Also return the cleaned_data at the end of the def clean() method - even if errors occurred.
def clean(self):
cleaned_data = super().clean()
email = cleaned_data.get("email")
password = cleaned_data.get("password")
...
# Don't forget to return the cleaned_data after everything
return cleaned_data
This is documented in the django docs:
https://docs.djangoproject.com/en/3.0/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other
The app has a basic registration form. I am trying to authenticate users after they fill it out. However, I'm unable to authenticate them. Am I going about this in the correct way?
Here is the view:
def registration(request):
if request.method == "POST":
form = CustomUserCreationForm(request.POST)
if form.is_valid():
user = request.user
password1 = form.cleaned_data['password1']
#this works
try:
validate_password(password1, user)
except ValidationError as e:
form.add_error('password1', e)
return render(request, 'register.html', {'form': form})
profile = form.save(commit=False)
profile.save()
user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password1'])
# this login not working, user is never authenticated
login(request, user)
return redirect('agree')
else:
raise ValidationError("Form is not valid. Try Again.")
else:
form = CustomUserCreationForm()
return render(request, 'register.html', {'form': form}).
Here is the forms.py. The model here is just the Django base user model.
class CustomUserCreationForm(forms.ModelForm):
username = forms.CharField(label='Username', widget=forms.TextInput(attrs={'class': "form-control"}))
password1 = forms.CharField(label='Password', widget=forms.PasswordInput(attrs={'class': "form-control"}))
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput(attrs={'class': "form-control"}))
class Meta:
model = User
fields = ['username']
def clean_password(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords do not match")
return password2
def save(self, commit=True):
user = super(CustomUserCreationForm, self).save(commit=False)
user.username = self.cleaned_data['username']
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
User never gets registered and authenticated.
For authenticate() method, you need to pass request(reference authenticate() method in django backend). For example:
authenticate(request, username=form.cleaned_data['username'], password=form.cleaned_data['password1'])
Also why do you need authenticate method as you already have the user object:
profile = form.save() # <-- Its an user instance, name of the variable should be user
login(request, profile, backend='django.contrib.auth.backends.ModelBackend')
return redirect('agree')
Finally, you implementation looks bit fishy, why are you using user=request.user, is the user already logged in? I think this part of code is unnecessary:
user = request.user
password1 = form.cleaned_data['password1']
try:
validate_password(password1, user)
except ValidationError as e:
form.add_error('password1', e)
return render(request, 'register.html', {'form': form})
I have a RegisterUserForm that is bound to a CustomUser (that extends AbstractUser). Before I save the user, I want to check password1 and password2 if they are equal but the clean(self) method is not called. the user is created even if the passwords are not the same.
I have read a lot of questions and tried a lot of things but couldn't find an answer. My code is below
I tried adding an init and a save method but still does not work.
class RegisterUserForm(forms.ModelForm):
password1=forms.CharField(label=_("password"), min_length=4)
password2=forms.CharField(label=_("repeat password"), min_length=4)
class Meta:
model = CustomUser
fields = ('first_name', 'last_name', 'email', 'password1','password2')
def save(self, *args, **kwargs):
self.full_clean()
return super().save(*args, **kwargs)
def clean(self):
cleaned_data = super().clean()
print("clean is called")
password1 = form.cleaned_data.get("password1")
password2 = form.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise ValidationError('password_mismatch')
return self.cleaned_data
and my view is
def register(request):
if request.method=='POST':
form = RegisterUserForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(form.cleaned_data['password1'])
user.save()
email = user.email
messages.success(request, f'user with {email} created successfully')
return redirect('home')
else:
form = RegisterUserForm()
return render(request, 'users/register.html', {'form':form })
i want to create a registration view so, it takes username, password, and email for registration and i am using Django User Model, but it is giving me an error.
AttributeError at /signup/
'SignUpForm' object has no attribute 'cleaned_data'
please tell me how to fix this,
forms.py
class SignUpForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Username'}))
email = forms.EmailField(widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Email'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Password'}))
confirm_password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder':
'Confirm Password'}), label="Confirm Password")
class Meta:
model = User
def __init__(self, *args, **kwargs):
super(SignUpForm, self).__init__(*args, **kwargs)
self.fields['username'].validators.append(ForbiddenUsernamesValidator)
self.fields['username'].validators.append(InvalidUsernameValidator)
self.fields['username'].validators.append(UniqueUsernameIgnoreCaseValidator)
self.fields['email'].validators.append(UniqueEmailValidator)
def clean(self):
super(SignUpForm, self).clean()
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if password and password != confirm_password:
self._errors['password'] = self.error_class(['Passwords don\'t match'])
return self.cleaned_data
views.py
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST or None)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
email = form.cleaned_data.get('email')
print(username)
print(password)
print(email)
messages.add_message(request, messages.SUCCESS, 'YOU ARE REGISTRED SUCCESSFULLY')
return render(request, 'authentication/signup.html', {})
else:
return render(request, 'authentication/signup.html', {'form': form})
else:
return render(request, 'authentication/signup.html', {'form': SignUpForm})
def clean(self):
self.cleaned_data = super(SignUpForm, self).clean()
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if password and password != confirm_password:
self._errors['password'] = self.error_class(['Passwords don\'t match'])
return self.cleaned_data
Hello i want to develop validation to user registration if user exists and is password matches the password confirmation field. Unfortunately, validation doesn't works. For example, if the 2 passwords don't match, the registration completes anyway with the first password. I want, if there is a problem to reload the registration form with the problems highlighted.
the form:
class RegistrationForm(forms.Form):
username = forms.CharField(label=u'Username', max_length=30)
first_name = forms.CharField(label=u'First Name', max_length=30)
last_name = forms.CharField(label=u'Last Name', max_length=30)
email = forms.EmailField(label=u'Email')
password1 = forms.CharField(
label=u'Password',
widget=forms.PasswordInput()
)
password2 = forms.CharField(
label=u'Password (Again)',
widget=forms.PasswordInput()
)
def clean_password2(self):
if 'password1' in self.cleaned_data:
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 == password2:
return password2
raise forms.ValidationError('Passwords do not match.')
def clean_username(self):
username = self.cleaned_data['username']
if not re.search(r'^\w+$', username):
raise forms.ValidationError('Username can only contain '
'alphanumeric characters and the underscore.')
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError('Username is already taken.')
the view:
def register_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email=form.cleaned_data['email']
)
UserProfile.first_name=form.cleaned_data['first_name']
created = UserProfile.objects.get_or_create(
user_id=user.id, first_name=form.cleaned_data['first_name'], last_name=form.cleaned_data['last_name'] )
return HttpResponseRedirect('/register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {
'form': form
})
return render_to_response(
'registration/register.html', variables)
class RegistrationForm(forms.Form):
//fields
def clean(self):
cleaned_data = super(RegistrationForm, self).clean()
username = cleaned_data.get("username")
password1 = cleaned_data.get("password1")
password1 = cleaned_data.get("password1")
#validate username
user = User.objects.filter(username=username)
if user:
raise forms.ValidationError(
"That user is already taken , please select another ")
elif not re.search(r'^\w+$', username):
raise forms.ValidationError(
"Username can only contain"
"alphanumeric characters and the underscore.")
#validate password
if password1 != password1:
raise forms.ValidationError(
"Your current and confirm password do not match.")
return cleaned_data
I use this simple validation which works.
def validate(self, value):
data = self.get_initial()
username = data.get("username")
email = data.get("email")
password = data.get("password")
confirm_password = data.get("confirm_password")
max_similarity = 0.7
user_qs = User.objects.filter(email=username)
if user_qs.exists():
raise ValidationError("Username already exist")
if(password != confirm_password):
raise ValidationError("Password and Confirm password does not match")
if SequenceMatcher(a=password.lower(), b=username.lower()).quick_ratio() > max_similarity:
raise serializers.ValidationError("The password is too similar to the username.")
if SequenceMatcher(a=password.lower(), b=email.lower()).quick_ratio() > max_similarity:
raise serializers.ValidationError("The password is too similar to the email.")
return data
Additional validation:
Also you can add some default validation of django by adding this.
This will check minimum length of the password and max string and max integer.
def validate_password(self, value):
try:
validate_password(value)
except ValidationError as exc:
raise serializers.ValidationError(str(exc))
return value