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
Related
I have created an extended User model and a form to register it. Since the form is filled out by an admin and not a user, the UserCreationForm has a random password generator to fill out password1 and 2, then set new password. This is great for a new user, but every time an admin edits the user profile, it will set a new password. I've looked at a few dozen examples here and on big G but can't seem to find a usable solution to know if the user has a password set.
I am re-using this form for update view, which is where I don't want the random password to be generated again. I tried doing the same if statement check as the username but it doesn't work the same way as the auth\form.py user.set_password is looking for password1.
class EmployeeRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True, widget=forms.EmailInput(attrs={'class': 'form-control mb-2',
'placeholder': 'Email address'}))
first_name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control mb-2',
'placeholder': 'First name'}))
last_name = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control mb-2', 'placeholder': 'Last name'}))
password1 = None
password2 = None
class Meta:
model = User
fields = ['email', 'first_name', 'last_name']
def clean(self):
password = User.objects.make_random_password(length=10,
allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')
self.cleaned_data['password1'] = password
self.cleaned_data['password2'] = password
return super().clean()
def save(self, commit=True):
user = super().save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
if user.username == '':
if len(user.first_name.split()) and len(user.last_name.split()) > 1:
username = f'{"".join(user.first_name.split()[:2])}{"."}{"".join(user.last_name.split())}'
elif len(user.first_name.split()) > 1:
username = f'{"".join(user.first_name.split()[:2])}{"."}{user.last_name}'
elif len(user.last_name.split()) > 1:
username = f'{user.first_name}{"."}{"".join(user.last_name.split())}'
else:
username = f'{user.first_name}{"."}{user.last_name}'
username = username.lower()
user.username = username
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
Update
Here is the profile_edit view where I verify the details of an existing user and save changes made through the form.
#login_required()
def profile_edit(request, slug, *args, **kwargs):
"""
Used for updating the Employee profile
"""
employee = Employee.objects.get(slug=slug)
employee_user = User.objects.get(id=employee.user.id)
form = EmployeeForm(request.POST or None, request.FILES or None, instance=employee)
user_form = EmployeeRegistrationForm(request.POST or None, instance=employee_user)
if 'cancel' in request.POST:
return redirect('corehr:employees')
elif request.method == 'POST':
form = EmployeeForm(request.POST or None, request.FILES or None, instance=employee)
user_form = EmployeeRegistrationForm(request.POST or None, instance=employee_user)
if form.is_valid() and user_form.is_valid():
form.save(commit=False)
user_form.save()
form.save()
messages.success(request, f'{employee.get_full_name}{" was updated successfully."}')
return redirect(reverse_lazy('corehr:profile', kwargs={'slug': slug}))
else:
messages.error(request, 'Please correct the errors listed below')
else:
form = EmployeeForm(request.POST or None, request.FILES or None, instance=employee)
user_form = EmployeeRegistrationForm(request.POST or None, instance=employee_user)
context = {'form': form, 'user_form': user_form}
return render(request, 'coreHR/profile_edit.html', context)
I ended up taking the suggestions from Abdul and Ranu. The are both right, so I just created a UserUpdateForm to update the data rather to 're-create' the user again. It all works as smooth as ever.
class UserUpdateForm(forms.ModelForm):
class Meta:
model = User
fields = ['email', 'first_name', 'last_name']
widgets = {
'email': forms.EmailInput(attrs={'class': 'form-control mb-2'}),
'first_name': forms.TextInput(
attrs={'class': 'form-control mb-2'}),
'last_name': forms.TextInput(
attrs={'class': 'form-control mb-2'}),
}
I replaced the reference in the profile_edit view from EmployeeRegistrationForm to UserUpdateForm. This was so simple an I was busting my head trying to work around several complex solutions which were going against the basics.
I want logged in user redirect to index when they attempt to go to the register form.
I manage to do to that, but I can't validate the register form when the a user who is not logged in complete it.
I have a custom view for signup:
class SignupView(UserPassesTestMixin, FormView):
template_name = 'main/auth/register.html'
form_class = forms.UserCreationForm
def test_func(self):
self.request.user.is_authenticated
def handle_no_permission(self):
if self.request.user.is_authenticated:
return redirect('main:index')
return self.get(self.request)
def get_success_url(self):
redirect_to = self.request.GET.get`enter code here`('next', 'main:index')
return redirect_to
def form_valid(self, form):
response = super().form_valid(form)
form.save()
email = form.cleaned_data.get('email')
first_name = form.cleaned_data.get('first_name')
raw_password = form.cleaned_data.get('password1')
logger.info('Nuevo registro para email=%s a través de SignupView', email)
user = authenticate(email=email, password=raw_password)
login(self.request, user)
form.send_mail()
return response
methods
test_func(self) and handle_no_permission(self) are used to test if the user is authenticated
but I think the problem is in return self.get(self.request) I use it to load the form but when I submit the form with correct data, it POST it to validate it, but just reload it again. I suppose I have to call form_valid but I can't figure out how.
Any help would be appreciated!! Regards
You can use the dispatch method of django CBV. Like below.
class SignupView(UserPassesTestMixin, FormView):
template_name = 'main/auth/register.html'
form_class = forms.UserCreationForm
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('main:index')
return super().dispatch(request, *args, **kwargs)
# other methods
This is function based views and its simple
views.py
to register
def register(request):
if request.user.is_authenticated:
return redirect(reverse('post_list'))
else:
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
new_user = user_form.save(commit=False)
new_user.set_password(
user_form.cleaned_data['password1']
)
new_user.save()
Profile.objects.create(user=new_user)
return render(
request,
'account/register_done.html',
{'new_user': new_user}
)
else:
user_form = UserRegistrationForm()
return render(
request,
'account/register.html',
{'user_form': user_form}
)
forms.py
class UserRegistrationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput(attrs={
'class': 'myfieldclass',
'placeholder': 'Password ...',
'type': 'password',
'name': 'password'
}))
password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput(attrs={
'class': 'myfieldclass',
'placeholder': 'Repeat Password ...',
'type': 'password',
'name': 'password'
}))
username = forms.CharField(label='Username', widget=forms.TextInput(attrs={
'class': 'myfieldclass',
'placeholder': 'Username ...',
'type': 'text',
'name': 'username'
}))
email = forms.CharField(label='Email', widget=forms.EmailInput(attrs={
'class': 'myfieldclass',
'placeholder': 'Email ...',
'type': 'email',
'name': 'email'
}))
class Meta:
model = User
fields = ('username', 'email')
help_texts = {
'username': '',
}
def clean_password2(self):
cd = self.cleaned_data
if cd['password1'] != cd['password2']:
raise forms.ValidationError(
'Passwords dosent Matched.')
return cd['password2']
I want to do ajax form validation to display errors. I looked at many examples, but some are old and do not work, while others I do not understand.Below is the code, please help with the implementation of ajax requests.
views.py
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
# Create a new user object but avoid saving it yet
new_user = user_form.save(commit=False)
# Set the chosen password
new_user.set_password(user_form.cleaned_data['password'])
# Save the User object
new_user.save()
return HttpResponse('IZI')
else:
print(user_form.errors)
user_form = UserRegistrationForm()
# errors = user_form.errors
data = {'user_form': user_form, 'errors': user_form.errors}
return render(request, 'registration.html', data)
# return HttpResponse(simplejson.dumps(errors))
else:
user_form = UserRegistrationForm()
return render(request, 'registration.html', {'user_form': user_form})
models.py
class TestUser(AbstractUser):
phone = PhoneNumberField(null=False, blank=False, unique=True)
class Meta:
db_table = '"fyzzys"."users"'
forms.py
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password', widget=forms.PasswordInput)
phone = PhoneNumberField(region='RU', required='true')
email = forms.CharField(error_messages='')
class Meta:
model = TestUser
fields = ('username', 'first_name', 'email', 'phone')
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords don\'t match.')
return cd['password2']
Here is an example but you'll need to adapt it to your needs and your code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js">
$.ajax({
url: 'your_url_for_register_view',
data: { password : 'your_password',
password2 : 'your_password',
phone : 'your_phone',
email : 'your_email',
csrfmiddlewaretoken : {{ csrf_token }},
},
success: function (data) {
//do something if successful
}
});
</script>
As per documentation : https://simpleisbetterthancomplex.com/tutorial/2016/08/29/how-to-work-with-ajax-request-with-django.html
found this in a tutorial but "password and confirm_password does not match" is not printing to html page.
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput())
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
email = forms.EmailField(max_length=254)
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'password','confirm_password']
def clean(self):
cleaned_data = super(UserForm, self).clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
raise forms.ValidationError(
"password and confirm_password does not match"
)
UPDATE:
Worked using {{form.non_field_errors}} in the template.
Numerous way you can do it,from your views,forms also from your model
Class UserForm(forms.ModelForm):
pass
def clean_password(self):
data = self.cleaned_data
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if password != confirm_password:
raise forms.ValidationError('Passwords must be same')
BTW
If using Python 3.6 then super().method_name(args),
if using 2.7 then super(class_name,self).method_name(args)
try:
def clean(self):
cleaned_data = super(UserForm, self).clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
raise forms.ValidationError(
"password and confirm_password does not match"
)
else:
form = UserForm()
# If form is not valid, this would re-render
return render(request, 'template.html', {'form': form})
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