Cleaned_data doesn't pass anything - python

I am working on a Django project and it seems like I can not use the cleaned_data module anywhere in my program. Every time I use it, it raises a key error (saying that key doesn't exist) and when I use cleaned_data.get it just passes nothing. I can use only "form.data" (as you can see in my code) and everything works fine. I just want to know why I can't use the cleaned_data?
here is my form.py:
class RegisterationForm(forms.Form):
first_name = forms.CharField
last_name = forms.CharField
username = forms.CharField
email = forms.EmailField
password = forms.CharField
password2 = forms.CharField
def clean(self):
password = self.cleaned_data.get('password')
password2 = self.cleaned_data.get('password2')
if password and password != password2:
raise forms.ValidationError("passwords do not match")
return self.cleaned_data
here is my view.py:
def register(request):
if request.method == 'POST':
form = RegisterationForm(request.POST)
if form.is_valid():
user_info={}
user_info['username'] = form.data['username']
user_info['first_name'] = form.data['first_name']
user_info['last_name'] = form.data['last_name']
user_info['password'] = form.data['password']
user_info['email']= form.data['email']
#salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
#usernamesalt = user_info['username']
#if isinstance(usernamesalt, unicode):
# usernamesalt = usernamesalt.encode('utf8')
user_info['activation_key'] = 1#hashlib.sha1(salt+usernamesalt).hexdigest()
form.sendEmail(user_info)
form.save(user_info)
return render_to_response('register_success.html',user_info)
else:
form_save = form
args = {}
args.update(csrf(request))
args['form'] = RegisterationForm()
return render_to_response('register.html',args)

Because you didn't call the parent class clean method to get the data first:
def clean(self):
cleaned_data = super(RegisterationForm, self).clean()
password = cleaned_data.get('password')
password2 = cleaned_data.get('password2')
if password and password != password2:
raise forms.ValidationError("passwords do not match")
Check out django doc about clean method.

If that's really your actual code, your form doesn't have any fields because you have not called any of the field definitions. It should be:
class RegisterationForm(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
username = forms.CharField()
email = forms.EmailField()
password = forms.CharField()
password2 = forms.CharField()

Related

How to use authenticate method with AbstractUser model django

I`m wrirting site on Django and I need to make a system for registration and authorization of work peepers, for this I use the Django AbstractUser model, registration works well, but authorization does not work, and the authenticate method returns None
Here is my JobseekerRegsiterInfo model:
class JobseekerRegisterInfo(AbstractUser):
username = first_name = last_name = None
id = models.BigAutoField(primary_key=True)
phone_number = PhoneNumberField()
email = models.EmailField(unique=True)
full_name = models.CharField(max_length=120)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['phone_number', 'full_name', 'hashed_password']
def __str__(self):
return self.full_name
My login form:
class JobseekerLoginForm(forms.Form):
email = forms.EmailField(label='Введіть ваш Email: ',
widget=forms.EmailInput(attrs={'class': 'form-control'}))
password = forms.CharField(label='Ваш пароль: ',
widget=forms.PasswordInput(attrs={'class': 'form-control'}))
def clean_email(self):
email = self.cleaned_data['email']
# if not select_field_value_from_model(JobseekerRegisterInfo, 'email', email):
if not JobseekerRegisterInfo.objects.filter(email=email):
raise forms.ValidationError('Неправильно введені email або пароль')
return email
and view function:
def jobseeker_login_view(request):
title = 'Авторизація'
context = {'title': title}
if request.method == 'POST':
form = JobseekerLoginForm(request.POST)
context['form'] = form
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(request, email=email, password=password)
print(generate_password_hash(password))
if user:
print(user)
else:
print('USER IS NONE')
else:
form_errors = form.errors.as_data()
custom_error = custom_error_service(form_errors)
context['list_first_error'] = custom_error
else:
form = JobseekerLoginForm()
context['form'] = form
return render(request, template_name='jobseeker/jobseeker_login.html', context=context)
But only USER IS NONE is displayed in the console, no matter what I do
Tell me, please, how to use authenticate correctly in my case

User Login Authentication using Django Model and form

I am trying to setup user authentication for the login page using forms and comparing it to my database value but it does not work. I also tried using this particular questions User Login Authentication using forms and Django logic to solve my problem but it didn't help.
Models.py
from django.db import models
from django.contrib.auth.password_validation import validate_password
class student(models.Model):
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
matric_number = models.CharField(max_length=9)
email = models.EmailField(max_length=50)
password1 = models.CharField(max_length=255, validators=[validate_password])
password2 = models.CharField(max_length=255)
def __str__(self):
return (self.matric_number)
This view saves user info to database
def student(request):
if request.method == 'POST':
form = studentForm(request.POST)
if form.is_valid():
sign_up = form.save(commit=False)
#sign_up.password1 = make_password(form.cleaned_data['password1'])
#sign_up.password2 = make_password(form.cleaned_data['password2'])
sign_up.status = 1
sign_up.save()
user = form.cleaned_data.get('matric_number')
messages.success(request, "Account was created for "+str(user))
return redirect(signin)
else:
form = studentForm()
return render(request, 'Student.html',{
"form": form
})
This is the signin view
def signin(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
try:
student = student.object.get(username=username, password=password)
return redirect(files)
except:
messages.success(request, "Error")
else:
form = LoginForm()
return render(request, "SignIn.html",{
"form":form
})
This is my form.py
class studentForm(forms.ModelForm):
class Meta:
model=student
fields="__all__"
widgets={
'first_name':forms.TextInput(attrs={'placeholder': 'Enter Your First Name'}),
'last_name':forms.TextInput(attrs={'placeholder': 'Enter Your Last Name'}),
'matric_number':forms.TextInput(attrs={'placeholder': 'Enter Your Matric Number'}),
'email':forms.EmailInput(attrs={'placeholder': 'abc#example.com'}),
'password1':forms.PasswordInput(attrs={'placeholder': 'Enter Your Preferred Password','id':'password'}),
'password2':forms.PasswordInput(attrs={'placeholder':'Confirm Your Password', 'id':'password1'})
}
def clean(self):
super(studentForm, self).clean()
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
matric_number = self.cleaned_data.get('matric_number')
email = self.cleaned_data.get('email')
try:
if password1 != password2:
self.errors[''] = self.error_class(["The two password fields must match"])
elif len(matric_number) != 9:
self.errors[''] = self.error_class(["You have entered an invalid matric number"])
elif len(matric_number) == 9:
matric_number = int(matric_number)
except ValueError:
self.errors[''] = self.error_class(["You have entered an invalid matric number"])
for instance in student.objects.all():
if instance.matric_number == str(matric_number):
self.errors[''] = self.error_class(["Matric number already exist"])
elif instance.email == email:
self.errors[''] = self.error_class(["E-mail address already exist"])
class LoginForm(forms.Form):
matric_number = forms.CharField(max_length=9, widget=forms.TextInput(attrs={'id': 'username', 'placeholder': 'Enter Your Staff Id Or Matric Number'}))
password1 = forms.CharField(max_length=9, widget=forms.PasswordInput(attrs={'id': 'password', 'placeholder':'Enter Your password'}))
Stop reinventing the wheel. Also, class names are supposed to be named with PascalCase.
Use AbstractUser model:
from django.contrib.auth.models import AbstractUser
class Student(AbstractUser):
...
and in your main urls.py:
from django.contrib.auth import views as auth_views
urlpatterns = [
...
path('login/', auth_views.LoginView.as_view(), name='login'),
...
]
It is much faster and SAFER way to create new user.
So I figured out out how to solve my problem. By using the AbstractUser model,i was able to create a custom user and then create another model which i extended a ForeignKey on the User model therefore allowing me to tie every user to their profile.
Here is my models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
pass
def __str__(self):
return self.username
class UserProfile(models.Model):
"""
This is the one for model.py
"""
username = models.ForeignKey(User, on_delete=models.CASCADE, null=True, default="")
profile_picture = models.ImageField(blank=True, null=True, default="")
matricno = models.CharField(max_length=9, default="", primary_key=True)
email = models.EmailField(default="")
first_name = models.CharField(max_length=200, default="")
last_name = models.CharField(max_length=255, default="")
class Meta:
verbose_name_plural = "Users Profile"
def __str__(self):
return self.first_name+ " "+self.last_name
And here is my views.py
def signup(request):
if request.method == "POST":
form = Signup(request.POST)
if form.is_valid():
username = request.POST["username"]
email = request.POST["email"]
password = request.POST["password"]
password2 = request.POST["password2"]
user = User.objects.create_user(
username=username,
password=password,
email=email,
)
user.save()
login(request, user)
messages.success(request, "Account Created successfully for " + username)
return redirect(details)
else:
form = Signup()
return render(request, "accounts/register.html", {"form": form})
def details(request, username):
user = User.objects.get(username=username)
form = Details()
if request.method == "POST":
form = Details(request.POST, request.FILES)
if form.is_valid():
detail = form.save(commit=False)
detail.username = request.user
detail.save()
return redirect(success, pk=detail.pk)
else:
form = Details(initial={"matricno":request.user.username})
return render(request, "details.html", {"form":form})
And finally my forms.py that i use in creating a signup form and perfoming validation
class Signup(forms.Form):
username = forms.CharField(
max_length=9,
widget=forms.TextInput(attrs={"placeholder": "Enter Your Matric Number"}),
)
email = forms.EmailField(
max_length=255,
widget=forms.EmailInput(attrs={"placeholder": "Enter Your E-mail Address"}),
)
password = forms.CharField(
max_length=255,
widget=forms.PasswordInput(
attrs={"placeholder": "Enter Your Password", "id": "password"}
),
)
password2 = forms.CharField(
max_length=255,
widget=forms.PasswordInput(
attrs={"placeholder": "Confirm Your Password", "id": "password2"}
),
)
def clean(self):
super(Signup, self).clean()
password = self.cleaned_data.get("password")
password2 = self.cleaned_data.get("password2")
username = self.cleaned_data.get("username")
email = self.cleaned_data.get("email")
if password != password2:
self.errors[""] = self.error_class(["The two password fields must match"])
for instance in User.objects.all():
if instance.username == str(username):
self.errors[""] = self.error_class(["User already exist"])
elif instance.email == email:
self.errors[""] = self.error_class(["E-mail already in use"])
else:
pass
return self.cleaned_data

Minimum length in password for django form

I am making a form in Django and I am using the "form.is_valid" to get all the error. Everything works except the minimum value for the password. I have following code for my form:
class RegisterationForm (forms.Form):
first_name = forms.CharField(initial ='' ,widget=forms.TextInput(attrs={'class' : 'form-control'}),max_length = 20)
last_name = forms.CharField(initial ='' ,widget=forms.TextInput(attrs={'class' : 'form-control'}),max_length = 20)
username = forms.CharField(initial ='' ,widget=forms.TextInput(attrs={'class' : 'form-control'}),min_length = 5,max_length = 20)
email = forms.EmailField(initial ='' ,widget=forms.TextInput(attrs={'class' : 'form-control'}))
password = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control'}))
password2 = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control'}))
def clean(self):
cleaned_data = super(RegisterationForm, self).clean()
password = self.cleaned_data['password']
password2 = self.cleaned_data['password2']
if password and password != password2:
raise forms.ValidationError("passwords do not match")
return self.cleaned_data
def clean_username(self):
username = self.cleaned_data['username']
return username
def clean_email(self):
email = self.cleaned_data['email']
return email
def clean_password(self):
password= self.cleaned_data['password']
if len(password) < 6:
raise forms.ValidationError("Your password should be at least 6 Characters")
return password
but here when I enter a password less than 6 characters, instead of getting a validation error I get an error from Django. The error is a key error which is caused because the cleaned_data dictionary does not contain the password when it's longer than 6 chars. I also used the min_length feature in form definition as well and the same thing happened.
If password or password2 is not valid, then they will not be in cleaned_data. You need to change your clean method to handle this. For example:
def clean(self):
cleaned_data = super(RegisterationForm, self).clean()
password = self.cleaned_data.get('password')
password2 = self.cleaned_data.get('password2')
if password and password2 and password != password2:
raise forms.ValidationError("passwords do not match")
You could specify min_length in your password field. Then Django will validate the length for you, and you can remove your custom clean method.
password = forms.CharField(min_length=6, widget=forms.TextInput(attrs={'class' : 'form-control'}))
Finally, your clean_username and clean_email methods are not doing anything so you can simplify your form by removing them.

How to allow user to change his attributes?

I'm trying to figure out how to allow users to change their profile. I have a Users extended by User Profile (OneToOne).
I was thinking about changing registration view, prefill user's attributes and allow him to change them. But it is not probably the good way.
Could you give me a hint how to do that?
class UserForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput())
password2 = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password1','password2', 'first_name', 'last_name')
def clean(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return self.cleaned_data
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('telephone','marital_status','how_do_you_know_about_us')
MODELS.PY
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
# ATRIBUTY KTORE BUDE MAT KAZDY
telephone = models.CharField(max_length=40,null=True)
HOW_DO_YOU_KNOW_ABOUT_US_CHOICES = (
('coincidence',u'It was coincidence'),
('relative_or_friends','From my relatives or friends'),
)
how_do_you_know_about_us = models.CharField(max_length=40, choices=HOW_DO_YOU_KNOW_ABOUT_US_CHOICES, null=True)
MARITAL_STATUS_CHOICES = (
('single','Single'),
('married','Married'),
('separated','Separated'),
('divorced','Divorced'),
('widowed','Widowed'),
)
marital_status = models.CharField(max_length=40, choices=MARITAL_STATUS_CHOICES, null=True)
# OD KIAL STE SA O NAS DOZVEDELI
# A STAV
def __unicode__(self):
return '{} {}'.format(self.user.first_name,self.user.last_name)
def __str__(self):
return '{} {}'.format(self.user.first_name,self.user.last_name)
REGISTRATION VIEW:
def register(request):
if request.method == 'POST':
user_form = UserForm(request.POST)
profile_form = UserProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user_form.cleaned_data['password1'])
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
return register_success(request)
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request, "auth/registration/register.html",
context={'user_form': user_form, 'profile_form': profile_form})
EDIT:
This is the view I'm trying to create but it does not autofill form:
#login_required
def edit_profile(request):
myUser = request.user
user_form = UserForm(request.POST, instance=myUser)
user_profile_form = UserProfileForm(request.POST, instance=myUser)
context={'user_form': user_form,
'user_profile_form':user_profile_form}
return render(request, 'auth/profiles/my_profile.html', context=context)
In the edit_profile view you added, you're passing your forms a POST request argument. You should only be passing this argument on a POST request. So update your forms to be the following if the request is a GET request:
views.py
user_form = UserForm(instance=myUser)
user_profile_form = UserProfileForm(instance=myUser)
forms.py
# Something like this will only save password if data is entered in one of the password fields
def clean(self):
cleaned_data = super(UserForm, self).clean()
password1 = cleaned_data.get('password1', None)
password2 = cleaned_data.get('password2', None)
old_password = cleaned_data.get('old_password', None)
if password1 or password2:
if password1 != password2:
self._errors['password1'] = 'New Password and Confirm New Password must match.'
self._errors['password2'] = 'New Password and Confirm New Password must match.'
if not self.user.check_password(old_password):
self._errors['old_password'] = 'Your old password was entered incorrectly.'
return cleaned_data
def save(self, request):
user = self.user
if self.cleaned_data.get('password1', None):
user.set_password(self.cleaned_data.get('password1'))
update_session_auth_hash(request, user)
user.save()
return user
For your choices issue, you can specify choices as an argument when specifying widgets for the field.

django email authentication

userform
class UserForm(forms.ModelForm):
confirm_password = forms.CharField(label="Confirm Password",widget=forms.PasswordInput(attrs = {'placeholder': 'Confirm Password','class':'required'}))
phone = forms.CharField(max_length = 15,widget = forms.TextInput(attrs = {'placeholder':'Enter mobile no. ','class':'required number'}))
profession = forms.CharField(max_length= 50,widget = forms.Select(choices = PROFESSION_CHOICES,attrs = {'class':'required'}))
email = forms.EmailField(label='Email address',max_length = 75,widget = forms.TextInput(attrs={'placeholder':'Enter a valid email.','class':'required email'}))
sex = forms.CharField(max_length = 20,label="I am :",widget=forms.Select(choices=SEX_CHOICES,attrs = {'class':'required'}))
password = forms.CharField(label="Password",widget=forms.PasswordInput(attrs = {'placeholder': 'Password','class':'required'}))
first_name = forms.CharField(max_length = 50,widget = forms.TextInput(attrs={'placeholder':'Please enter your real name.','class':'required alphabets'}))
last_name = forms.CharField(max_length = 50,widget = forms.TextInput(attrs={'placeholder':'Enter last name.','class':'required alphabets'}))
def clean_first_name(self):
first_name = self.cleaned_data['first_name']
if first_name == '':
raise forms.ValidationError("This field is required.")
def clean_phone(self):
phone = self.cleaned_data['phone']
if phone == '':
raise forms.ValidationError("This field is required.")
def clean_last_name(self):
last_name = self.cleaned_data['last_name']
if last_name == '':
raise forms.ValidationError("This field is required.")
def clean_email(self):
email = self.cleaned_data.get("email")
try:
user = User.objects.get(email = email)
raise forms.ValidationError("Email already in use.")
except User.DoesNotExist:
return email
def clean_profession(self):
profession = self.cleaned_data['profession']
if profession == "":
raise forms.ValidationError("Select a valid option.")
def clean_sex(self):
sex = self.cleaned_data['sex']
if sex == "":
raise forms.ValidationError("Select a valid option.")
def save(self,*args,**kw):
user = super(UserForm,self).save(*args,**kw)
user.set_password(self.cleaned_data.get("password"))
user.first_name = self.cleaned_data.get("first_name")
user.last_name = self.cleaned_data.get("last_name")
user.email = self.cleaned_data.get("email")
user.save()
user.get_profile().phone = self.cleaned_data.get('phone')
user.get_profile().location = self.cleaned_data.get('location')
user.get_profile().profession = self.cleaned_data.get('profession')
user.get_profile().sex = self.cleaned_data.get('sex')
return user
class Meta:
model = User
fields = ('username','email','password','confirm_password','first_name','last_name','sex','phone','profession')
widgets = {
'password': forms.PasswordInput(),
}
user registration view
def register_user(request):
if request.POST:
data = request.POST.copy()
data["username"] = 'user'
rform = UserForm(data)
#form = UserProfileForm()
if rform.is_valid():
try:
user = rform.save()
user.username = "user"+str(user.id)
user.save()
user = authenticate(username = user.username,password=user.password)
#register user
login(request,user)
return redirect(index)
except:
print "Unexpected error"
raise
else:
# submit the same form again.
form = LoginForm();
sform = LoginForm()
return render_to_response('register.html',{'rform':rform,'form':form,'sform':sform},context_instance = RequestContext(request))
else:
rform = UserForm()
#form = UserProfileForm()
form = LoginForm()
sform = LoginForm()
return render_to_response('register.html',{'rform':rform,'form':form,'sform':sform},context_instance = RequestContext(request))
error
IntegrityError at /accounts/register/
auth_user.first_name may not be NULL
doubt
When i was using the normal user authentication , everything was working perfectly but when i am using it with email authentication , it gives me the above error ,
how do i get past this error , please help , and also how do i make the email field unique as in how do i add index to this field , please help
Your custom field cleaning methods (clean_*) do not return the cleaned value. From the form validation docs: https://docs.djangoproject.com/en/1.4/ref/forms/validation/
Just like the
general field clean() method, above, this method should return the
cleaned data, regardless of whether it changed anything or not.
clean_first_name does not have a return which is the same as returning None and the reason why Django is trying to insert a NULL for this field.

Categories

Resources