Email forms do not match in Django Custom-User registration - django

I'm setting up a custom-user registration form to create an account on my Django project. I feel I'm missing something very simple that keeps me from registering for some reason.
My registration form demands 4 fields to be filled before a new user can register. Of these 4 fields, two are just a confirmation of the email address.
Here is a copy of my form.py:
class UserRegisterForm(forms.ModelForm):
username = forms.CharField(label='Username')
email = forms.EmailField(label='Email Address')
email2 = forms.EmailField(label='Confirm Email')
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = CustomUser
fields = ['username', 'email', 'email2', 'password']
def clean_email(self):
email = self.cleaned_data.get('email')
email2 = self.cleaned_data.get('email2')
if email != email2:
raise forms.ValidationError("Emails do not match")
And here is a copy of my view.py:
def register_view(request):
next = request.GET.get('next')
form = UserRegisterForm(request.POST or None)
if form.is_valid():
user = form.save(commit=False)
password = form.cleaned_data.get('password')
user.set_password(password)
user.save()
new_user = authenticate(username=user.username, password=password)
login(request, new_user)
if next:
return redirect(next)
return redirect('/home/')
context = {'form':form, "title":"register"}
return render(request, "register.html", context)
Here is my html file:
<h2><center><font color="white">Register Here:</font></center></h2>
<form method="POST"><center>
{% csrf_token %}
{{form}}
<input type="submit" />
</center></form>
Whenever I try to register as a new user, my form validation error is raised as is says that my two emails do not match (I copy-paste them to make sure they are identical).
I feel I'm missing something that is right under my nose...
Cheers to all of you and thank you very much.

try this
def register_view(request):
next = request.GET.get('next')
form = UserRegisterForm(request.POST or None)
if form.is_valid():
email = form.cleaned_data.get('email')
email1 = form.cleaned_data.get('email1')
if email1 == email
user = form.save(commit=False)
password = form.cleaned_data.get('password')
user.set_password(password)
user.save()
new_user = authenticate(username=user.username, password=password)
login(request, new_user)
if next:
return redirect(next)
else:
….

def clean(self):
cleaned_data = super(UserRegisterForm, self).clean()
email = cleaned_data.get('email')
email2 = cleaned_data.get('email2')
if email != email2:
self.add_error("email", "Emails do not match")
The problem is that in clean_email method you have email2 to be always None. To compare two or more fields use clean method

Related

model form has no attribute 'cleaned_data'

I want to sign in to be able to use the site. However, I'm having a problem: 'LoginForm' object has no attribute 'cleaned_data'. Please tell me how can I solve it. I apologize in advance for my English
My forms.py
class LoginForm(forms.Form):
user_name = forms.CharField(max_length=20, widget=TextInput(attrs={'type':'text','class': 'form-control','placeholder': 'Input username'}))
passWord = forms.CharField(max_length=25, widget=TextInput(attrs={'type':'password','class': 'form-control','placeholder': 'Input password'}))
class Meta:
fields = ['user_name', 'passWord']
My views.py
def login_view(request):
template_name = 'main/login.html'
action_detail = ''
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid:
username = form.cleaned_data.get('user_name')
password = form.cleaned_data.get('passWord')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('/')
else:
action_detail = 'invalid username or password'
else:
form = LoginForm()
context={
'title': 'Login',
'form': form,
'action_detail': action_detail,
}
return render(request, template_name, context)
is_valid is a function.
https://docs.djangoproject.com/en/4.0/ref/forms/api/#django.forms.Form.is_valid
You should call it.
if form.is_valid():

Django - user should have is_active = False but it is showing active in admin

My custom signup view has the user's is_active set to False. They use an emailed authorized token to set is_active to True. However, immediately after I sign up as a new user, I log into the admin page as a superuser and I can see that my new user has active checked off.
views
def signup(request):
if request.method == 'POST':
form = CustomUserCreationForm(request.POST)
if form.is_valid():
user = form.save()
user.is_teacher = True
user.is_staff = True
user.is_active = False
to_email = form.cleaned_data.get('email')
user.username = to_email # make the username the same as the email
user.save()
group = Group.objects.get(name='teacher')
user.groups.add(group)
current_site = get_current_site(request)
# use sendgrid api for email
sendgrid_client = SendGridAPIClient(
api_key=os.environ.get('SENDGRID_API_KEY'))
from_email = From("me#email.com")
to_email = To(to_email)
subject = "Activate your SmartMark Account"
active_link = render_to_string('account/acc_active_email_link.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
html_text = f'Hello {user}<br/><p>Registration email</p>{active_link}'
html_content = HtmlContent(html_text)
mail = Mail(from_email, to_email, subject,
html_content)
response = sendgrid_client.send(message=mail)
return redirect(reverse('accounts:account_activation_sent'))
else:
form = CustomUserCreationForm()
return render(request, 'account/signup.html', {'form': form})
def account_activation_sent(request):
return render(request, 'account/account_activation_sent.html')
def activate(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = CustomUser.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
# calls check_token function but user is already set to active - email and token
# were never used.
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.save()
login(request, user)
return redirect('home')
else:
return render(request, 'account/account_activation_invalid.html')
CustomUser model
class CustomUser(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
is_teacher = models.BooleanField('teacher status', default=False)
def __str__(self):
return self.username
Form
class CustomUserCreationForm(UserCreationForm):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
class Meta:
model = get_user_model()
fields = ('email', 'first_name', 'last_name')
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
def clean_email(self):
value = self.cleaned_data["email"]
if not value:
raise forms.ValidationError('An Email address is required.')
check_users = CustomUser.objects.filter(email__iexact=value)
if check_users:
raise forms.ValidationError('This email is already in use.')
return value
I am using Django's built in authentication. I am expecting the Active in the admin panel to be not checked off. I also tried moving the user.is_active=False to after the user.save() but this did not change the behaviour. I know from looking at my inital migrations file that the default for is_active is True but I would think that my signup view would override this
Edit
I thought I had fixed this by changing to user=form.save(commit=False) but it's happening again. New sign ups are automatically active.
First I changed my form save to:
user=form.save(commit=False)
However, it appears that the problem is that when I email the authorization token, the email recipient is checking the url for spam. By checking that the token url is a valid, the token is getting validated. I add a POST form such that the token is not checked until the user submits the form.

Django User Creation successful, but authenticate() returning None

I wrote a custom page to create a new user. The user gets successfully created, however if I try to login with the correct credentials, authentication is returning None.
If I go into the Django Admin, I can create a new password for the user I just created and then login is successful. any ideas?
Create User Function:
def create_account(request):
if request.method == "POST":
# Default User Fields
username = request.POST['username']
password = request.POST['password']
email = request.POST['email']
first_name = request.POST['first_name']
last_name = request.POST['last_name']
try:
user = User.objects.create_user(username,email,password,first_name=first_name, last_name=last_name)
user.save()
user_profile = models.User_Profile.objects.create_user_profile(user)
user_profile.save()
response = {'success': True}
return HttpResponse(json.dumps(response))
except Exception, e:
response = {'success': False}
return HttpResponse(json.dumps(response))
Login function:
def site_login(request):
#TODO: GET THIS WORKING
if request.method == "POST":
user = authenticate(username=request.POST['username'], password=request.POST['password'])
if user is not None:
if user.is_active:
login(request, user)
response = {'success':True}
return HttpResponse(json.dumps(response))
else:
response = {'success':False,'message':'Account has been disabled.'}
return HttpResponse(json.dumps(response))
else:
response = {'success':False,'message':'Invalid username or password.'}
return HttpResponse(json.dumps(response))
You need to use set_password when creating a user (https://docs.djangoproject.com/en/1.9/ref/contrib/auth/#django.contrib.auth.models.User.set_password). Try doing:
def create_account(request):
if request.method == "POST":
# Default User Fields
username = request.POST.get('username')
password = request.POST.get('password')
email = request.POST.get('email')
first_name = request.POST.get('first_name')
last_name = request.POST.get('last_name')
try:
# illustrating it out for you
user = User()
user.username = username
user.email = email
user.set_password(password)
user.first_name = first_name
user.last_name = last_name
user.save()
user_profile = models.User_Profile.objects.create_user_profile(user)
user_profile.save()
response = {'success': True}
return HttpResponse(json.dumps(response))
except Exception, e:
response = {'success': False}
return HttpResponse(json.dumps(response))

Django KeyError at /register/

I have a registration that let users register and i'm having difficulty fixing it.
The problem is when a user submits a single field instead of the whole form for example an email . I get this error
KeyError at /register/
password
Request Method: POST
Request URL: http://127.0.0.1:8000/register/
File "C:\Python26\Lib\site-packages\django\forms\forms.py" in _get_errors
115. self.full_clean()
File "C:\Python26\Lib\site-packages\django\forms\forms.py" in full_clean
271. self._clean_form()
File "C:\Python26\Lib\site-packages\django\forms\forms.py" in _clean_form
299. self.cleaned_data = self.clean()
File "C:\o\17\mysite\pet\forms.py" in clean
31. if self.cleaned_data['password'] != self.cleaned_data['password1']:
Exception Type: KeyError at /register/
Exception Value: password
I tried to fix this solution using if . If user has a submitted a username or any other required field , process the form otherwise redisplay the original form.
but I still get the same error.
This is my edited views.py (at the bottom of the page is my original RegistrationForm)
def PetRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('world:HappyLand'))
if request.method =='POST':
form = UserRegistration(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
if username:
email=form.cleaned_data['email']
if email:
password=form.cleaned_data['password']
if password:
user = User.objects.create_user(
username=form.cleaned_data['username'],
email=form.cleaned_data['email'],
password=form.cleaned_data['password']
)
user.is_active = True
user.first_name = form.cleaned_data['name']
user.save()
person = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password']
)
Person.objects.create(user_id=user.id,
name=form.cleaned_data['name'],birthday=form.cleaned_data['birthday'])
login(request, person)
return HttpResponseRedirect(reverse('world:HappyLand'))
return render(request, 'register.html', {'form': UserRegistration()})
How can I fix this error and also how could I display an error message on the other fields that the user didn't fill out like "Error Missing Field , Please Fill this Field".
def PetRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('world:HappyLand'))
if request.method =='POST':
form = UserRegistration(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
email=form.cleaned_data['email'],
password=form.cleaned_data['password']
)
user.is_active = True
user.first_name = form.cleaned_data['name']
user.save()
person = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password']
)
Person.objects.create(user_id=user.id,
name=form.cleaned_data['name'],birthday=form.cleaned_data['birthday'])
login(request, person)
return HttpResponseRedirect(reverse('world:HappyLand'))
return render(request, 'register.html', {'form': UserRegistration()})
My forms.py
class UserRegistration(forms.Form):
username = forms.CharField()
name = forms.CharField()
email = forms.EmailField()
birthday = forms.DateField(widget=extras.SelectDateWidget(years=range(1950, 2012)))
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
password1 = forms.CharField(
label=(u'Verify Password'),
widget = forms.PasswordInput(render_value=False)
)
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(
"That user is already taken , please select another ")
def clean(self):
if self.cleaned_data['password'] != self.cleaned_data['password1']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
My models.py
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100, blank=True)
birthday = models.DateField(blank=True,null=True)
def __unicode__(self):
return self.name
Problem is with your clean(). In clean(), you are trying to access field password on form's cleaned_data. password will only be available on cleaned_data if the user has filled this field. So, you must check that password is there in cleaned_data before trying to access it.
Changing your clean():
def clean(self):
if 'password' in self.cleaned_data and 'password1' in self.cleaned_data and self.cleaned_data['password'] != self.cleaned_data['password1']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
You can provide a keyword argument error_messages on form field for showing error message like "Error Missing Field , Please Fill this Field".
class SomeForm(forms.Form):
name = forms.CharField(error_messages={'required':'Error Missing Field , Please Fill this Field'})
There is a bug in your view.
is_valid() populates errors on the form but this same form instance must be sent to the template so that you can access the errors on the form's fields.
But in your view, you have only one call to render() which gets called even in case of an invalid form on a post request. And in this render(), you are creating a new instance of form. So, this new form which you are sending to template will not have any errors.
So, making slight modification to your view:
def PetRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('world:HappyLand'))
form = UserRegistration() #This will be used in GET request
if request.method =='POST':
form = UserRegistration(request.POST) #This will be used in POST request
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
email=form.cleaned_data['email'],
password=form.cleaned_data['password']
)
user.is_active = True
user.first_name = form.cleaned_data['name']
user.save()
person = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password']
)
Person.objects.create(user_id=user.id,
name=form.cleaned_data['name'],birthday=form.cleaned_data['birthday'])
login(request, person)
return HttpResponseRedirect(reverse('world:HappyLand'))
return render(request, 'register.html', {'form': form})
Notice in your view, I have added form=UserRegistration() before checking if its POST request, and have added the comment at two places where we are instantiating UserRegistration. And then in render(), you should send this form.
Then your {{form.username.errors}} will work.
I just modified your forms.py
class UserRegistration(forms.Form):
username = forms.CharField()
name = forms.CharField()
email = forms.EmailField()
birthday = forms.DateField(widget=extras.SelectDateWidget(years=range(1950, 2012)))
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
password1 = forms.CharField(
label=(u'Verify Password'),
widget = forms.PasswordInput(render_value=False)
)
def clean(self):
cleaned_data = super(UserRegistration, self).clean()
username = cleaned_data.get("username")
password = cleaned_data.get("password")
password1 = cleaned_data.get("password1")
#check if username exist
user = User.objects.filter(username=username)
if user:
raise forms.ValidationError(
"That user is already taken , please select another ")
#check password
if password != password1:
raise forms.ValidationError(
"Your current and confirm password do not match.")
return cleaned_data

UserProfile Registration erases all rows

I have created a user registration view and this is it:
def register(request):
if request.method == 'POST':
data = request.POST.copy() # so we can manipulate data
# random username
data['username'] = hashlib.md5( data['email'] ).hexdigest()
data['username'] = data['username'][0:30]
#data['username'] = ''.join([choice(letters) for i in xrange(30)])
form = RegisterForm(data)
if form.is_valid():
new_user = form.save()
#UserProfile.objects.create(user=new_user)
return HttpResponse("Thanks for Registering")
else:
form = RegisterForm()
return render_to_response("CTUser/register.html", { 'form': form, })
When I uncommented the UserProfile line:
#UserProfile.objects.create(user=new_user)
the email and password are saved correctly, but when It is there, all the info is erased. Am I doing something wrong here?
here is the UserProfile classs:
class UserProfile(User):
user = models.OneToOneField(User)
#user = models.ForeignKey(User, unique=True)
#profile sub URL
pagelink = models.CharField(max_length=40)
#one or many albums
albums = models.ManyToManyField(Album)
UPDATE(10/19/11):
Here is the registration form function:
class RegisterForm(UserCreationForm):
email = forms.EmailField(label = "Email Address", max_length=75)
class Meta:
model = User
#exclude = ['username',]
fields = ("username", "email")
def clean_email(self):
email = self.cleaned_data["email"]
try:
user = User.objects.get(email=email)
raise forms.ValidationError("This email address already exists. Did you forget your password?")
except User.DoesNotExist:
return email
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.email = self.cleaned_data["email"]
user.is_active = True # change to false if using email activation
if commit:
user.save()
return user
Check if new_user contains all data you want to save. Paste RegisterForm code.
EDIT
try to change:
user = super(UserCreationForm, self).save(commit=False)
into
user = super(RegisterForm, self).save(commit=False)