object has no clean_data attribute Django - python

So I have been working on my first Django project and I have run into an issue I cannot figure out. When I run my dev server I get the following error:
AttributeError at /register/
'RegistrationForm' object has no attribute 'clean_data'
I have browsed the forums with little luck.
Here is the code:
Views Page:
def register_page(request):
if request.method=='POST':
form=RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email'])
return HttpResponseRedirect('/')
else:
form = RegistrationForm()
variables = RequestContext(request, {
'form': form})
return render_to_response(
'registration/register.html',
variables
)
Forms page:
class RegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=30)
email = forms.EmailField(label='Email')
password1 = forms.CharField(
label='Password (Again)',
widget=forms.PasswordInput()
)
password2 = forms.CharField(
label='Password (Again)',
widget=forms.PasswordInput()
)
def clean_password2(self):
if 'password1' in self.clean_data:
password1 = self.clean_data['password1']
password2 = self.clean_data['password2']
if password1 == password2:
return password2
raise forms.ValidationError('Passwords do not match.')
def clean_username(self):
username = self.clean_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 ObjectDoesNotExist:
return username
raise forms.ValidationError('Username is already taken.')
Thanks,
Seth

You have mispelled the name of the attribute. Use cleaned_data instead.

Related

django sign up form not storing the username

I have a sign up form that does not store the username properly, other fields are stored successfully. Shouldn't it save the username because it is in the fields ? I saw that I cannot login and this is because the row in the table does not have the username.
views.py
class SignUpFormView(FormView):
form_class = SignUpForm
template_name = 'users/authentication/login/signup.html'
def post(self, request):
form = self.form_class(data=request.POST)
if form.is_valid():
user = form.save(commit=False)
# some logic here
user.save()
messages.success(
request, "Great! You are able to login now.")
return redirect('login')
else:
messages.error(request, form.errors)
return redirect('login')
forms.py
class CustomUserCreationForm(UserCreationForm):
def clean_username(self):
username = self.cleaned_data["username"]
try:
TbUser.objects.get(username=username)
except TbUser.DoesNotExist:
return username
raise forms.ValidationError(self.error_messages['duplicate_username'])
class Meta(UserCreationForm.Meta):
model = TbUser
class SignUpForm(CustomUserCreationForm):
email = forms.EmailField()
customer_id = forms.CharField(label="Customer ID")
def clean_username(self):
data = self.cleaned_data['username']
if TbUser.objects.filter(username=data).exists():
raise forms.ValidationError(
"Username already exists. Pick another one")
def clean(self):
cd = self.cleaned_data
password1 = cd.get("password1")
password2 = cd.get("password2")
if password1 != password2:
raise ValidationError("Passwords did not match")
return cd
class Meta:
model = TbUser
fields = ['username', 'email', 'real_name', 'customer_id',
'password1', 'password2']
The clean_username method of SignUpForm does not return anything. You need to return cleaned data for it. So add return data to the bottom of this method.

Django - How to create a user-owned group when registering?

I'm using Django. User registration form contains fields such as username, e-mail, password. I want the user to create their own group when registering. How do I add this field?
forms.py
class RegisterForm(forms.ModelForm):
username = forms.CharField(max_length=100, label='Kullanıcı Adı')
email = forms.EmailField(max_length=200, help_text='Required')
password1 = forms.CharField(max_length=100, label='Parola', widget=forms.PasswordInput)
password2 = forms.CharField(max_length=100, label='Parola Doğrulama', widget=forms.PasswordInput)
class Meta:
model = User
fields = [
'username',
'email',
'password1',
'password2',
]
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("Parolalar eşleşmiyor!")
return password2
def clean_email(self):
email = self.cleaned_data.get('email')
lenghtw = len(User.objects.filter(email=email))
if lenghtw > 0 :
raise forms.ValidationError('Bu email adresine sahip bir kullanıcı zaten var.')
return email
views.py
def register_view(request):
form = RegisterForm(request.POST or None)
if form.is_valid():
user = form.save(commit=False)
password = form.cleaned_data.get('password1')
user.set_password(password)
#user.is_staff = user.is_superuser = True
user.save()
new_user = authenticate(username=user.username, password=password)
login(request, new_user)
return redirect('home')
return render(request, 'accounts/form.html', {'form': form, 'title': 'Üye Ol'})
The screenshot OP gave as a comment is more explicit than his/her question, which should be edited :-)
As a summary:
thanks to a view + form, you want to create a new user and a new group (Grup Name field),
when your user is created, you want your user to automatically belong to your new group.
A few issues I see in your approach:
you are coding a form which already exists in Django (UserCreationForm from django.contrib.auth.forms), with unnecessary checks (as for password validation: it has already been done by Django),
your field Grup name is not in your form by the way, did you forget it?
your user needs to be saved to database already, so it can have a pk and be added to a group.
We could also use signals to do so, but let's go with your own approach:
# forms.py
from django.contrib.auth.forms import UserCreationForm
class RegisterForm(UserCreationForm):
new_group_name = forms.CharField(max_length=100, label='Grup Name')
def clean_new_group_name(self):
# if you need to check the name of the group name
[...]
# views.py
def register_view(request):
form = RegisterForm(request.POST or None)
if form.is_valid():
user = form.save() # <--- ! don't use commit=False here
password = form.cleaned_data.get('password1')
new_group_name = form.cleaned_data['new_group_name']
new_group, created = Group.objects.update_or_create(name=new_group_name)
user.groups.add(Group.objects.get(name=new_group_name)
user.save()
new_user = authenticate(username=user.username, password=password)
login(request, new_user)
return redirect('home')
return render(request, 'accounts/form.html', {'form': form, 'title': 'Üye Ol'}
Could you try if that works for you?

How do I control what authenticated users can see in Django?

Trying to hide a view to create a restaurant from anyone other than a restaurant Owner.
Used examples shown using groups and testing whether a user is in that group or not but nothing seems to work.
views.py
def is_owner(user):
if user.objects.filter(name="Owner").exists():
return True
class CreateRestaurantView(generic.CreateView):
form_class = CreateRestaurantForm
success_url = reverse_lazy('home')
template_name = 'signup.html'
#login_required
def create_restaurant(request):
if is_owner == True:
if request.method == "POST":
form = CreateRestaurantForm(request.POST)
if form.is_valid():
restaurant = form.save(commit=False)
restaurant.Restaurant_Owner = request.user
restaurant.save()
return redirect('restaurant_list')
else:
form = CreateRestaurantForm()
return render(request, 'create_restaurant.html', {'form': form})
else:
return render(request, 'home.html')
forms.py
signup form for Owners
class OwnerCreationForm(forms.ModelForm):
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(OwnerCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
group = Group.objects.get(name='Owner')
user.groups.add(group)
return user
I'm trying to get the view to show the create_restaurant form when a user belongs to the "Owner" group but the function to test (is_owner) does not work and is always false.
First of all, you are defined is_owner as function, so, you should call it as is_owner(any_user_object)
Second thing is, to search over the Group, it should be as
user.groups.filter(name="Owner").exists()
code snippet
def is_owner(user):
return user.groups.filter(name="Owner").exists()
#login_required
def create_restaurant(request):
if is_owner(request.user) == True:
if request.method == "POST":
form = CreateRestaurantForm(request.POST)
if form.is_valid():
restaurant = form.save(commit=False)
restaurant.Restaurant_Owner = request.user
restaurant.save()
return redirect('restaurant_list')
else:
form = CreateRestaurantForm()
return render(request, 'create_restaurant.html', {'form': form})
else:
return render(request, 'home.html')
UPDATE-1
change the save() method of OwnerCreationForm as below
class OwnerCreationForm(forms.ModelForm):
# your other code
def save(self, commit=True):
user = super(OwnerCreationForm, self).save(commit=True)
user.set_password(self.cleaned_data["password1"])
if not user.groups.filter(name="Owner").exists():
group = Group.objects.get(name='Owner')
user.groups.add(group)
user.save()
return user

Django error: UNIQUE constraint failed: auth_user.username

I need to register a user by sending an activation token to her Email address. I am getting this error (UNIQUE constraint failed: auth_user.username) when trying to register her using custom built-in functions register and activate.
My code is as follows:
forms.py
class UserRegisterForm(forms.Form, UserCreationForm):
username = forms.CharField(max_length=20)
date_of_birth = forms.DateField(widget=forms.SelectDateWidget(years=range(2017, 1900, -1)))
email = forms.EmailField()
def clean_username(self):
username = self.cleaned_data.get('username')
if User.objects.filter(username__iexact=username).exists():
raise forms.ValidationError('Username already exists')
return username
def clean_date_of_birth(self):
'''
Only accept users aged 13 and above
'''
userAge = 13
dob = self.cleaned_data.get('date_of_birth')
today = date.today()
if (dob.year + userAge, dob.month, dob.day) > (today.year, today.month, today.day):
raise forms.ValidationError('Users must be aged {} years old and above.'.format(userAge))
return dob
def clean_email(self):
email = self.cleaned_data.get('email')
if User.objects.filter(email__iexact=email).exists():
raise forms.ValidationError('A user has already registered using this email')
return email
def clean_password2(self):
'''
we must ensure that both passwords are identical
'''
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise forms.ValidationError('Passwords must match')
return password2
views.py
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password1')
new_user = User.objects.create(username=username, email=email, password=password)
new_user = form.save(commit=False)
#new_user.set_password(password) # hashes the password
new_user.is_active = False
new_user.save()
current_site = get_current_site(request)
message = render_to_string('email_activation_link.html', {
'new_user':new_user,
'domain':current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(new_user.pk)),
'token': account_activation_token.make_token(new_user),
})
mail_subject = 'Activate your Frac account.'
#to_email = form.cleaned_data.get('email')
email = form.cleaned_data.get('email')
to_email = EmailMessage(mail_subject, message, to=[email])#[to_email])
to_email.send()
return render(request, 'register_confirm.html', {'form': form})
else:
form = UserRegisterForm()
return render(request, 'register.html', {'form': form})
spec_backend = 'django.contrib.auth.backends.ModelBackend'
def activate(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
new_user = User.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
new_user = None
if new_user is not None and account_activation_token.check_token(new_user, token):
new_user.is_active = True
new_user.save()
return render(request, 'register_complete.html', {})
else:
return render(request, 'registration_incomplete.html', {})
What is causing such an error? I researched similar posts on this platform but each case is unique.
You are getting the unique constraint error because you are trying to create the same user twice:
new_user = User.objects.create(username=username, email=email, password=password)
new_user = form.save(commit=False)
...
new_user.save()
Since you are using a model form, you don't need to call User.objects.create() manually. Remove that line. You can also remove the three lines above that fetch username, email and password from the cleaned data.
No need of such confusing type of answers , here's the simplest one that can be added to views.py, wherever you have handled your signup form.
It will just show the error without showing the default
(*Dont Copy this one)
UNIQUE constraint failed auth_user.username
Here's the code :-
(*Copy this one)
if User.objects.filter(username = username).first():
messages.error(request, "This username is already taken")
return redirect('home')

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.

Categories

Resources