I'm trying to create edit user profile functionality. But I get the following error. I feel like it's trying to create a new user instead of editing the existing one. So that might result into username not being unique. I've no idea what to change/add here.
Here is my views
def showProfile(request, id):
profile = DoctorSeeker.objects.get(id=id)
return render(request,'meddy1/seekerprofile.html',{'doctorSeeker': profile})
def update_profile(request):
args = {}
if request.method == 'POST':
form = UserUpdateForm(request.POST)
if form.is_valid():
form.save()
return render(request, showProfile())
else:
form = UserUpdateForm()
args['form'] = form
return render(request, 'meddy1/editseekerprofile.html', args)
Here is my forms
class UserUpdateForm(forms.ModelForm):
name = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'FirstName LastName'}))
email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Please enter a valid email address so we can reach you. No spam. Ever.'}))
password1 = forms.CharField(label="Old Password",widget=forms.PasswordInput(attrs={'class': 'form-control','placeholder':'Enter your password to save the changes.'}),required=False)
password2 = forms.CharField(label="New Password?",widget=forms.PasswordInput(attrs={'class': 'form-control','placeholder':'Only enter new password if you want to change it.'}),required=False)
password3 = forms.CharField(label="Confirm New Password",widget=forms.PasswordInput(attrs={'class': 'form-control','placeholder':'Confirm New Password'}),required=False)
class Meta:
model = DoctorSeeker
fields = ("name","email")
class Meta:
model = User
fields = ("password2", "password3")
def clean_password2(self):
password2 = self.cleaned_data.get("password2")
password3 = self.cleaned_data.get("password3")
if password2 and password3 and password2 != password3:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def save(self, commit=True):
user = super(UserUpdateForm, self).save(commit=False)
user.set_password(self.cleaned_data["password2"])
fullName = self.cleaned_data["name"]
Email = self.cleaned_data["email"]
if commit:
user.save()
userProfile = DoctorSeeker(user=user, name=fullName, email=Email)
userProfile.save()
return user
the save method of django form will create a new object (if no instance are suplied) and not an update of this one. You have to retreive your user first pass the instance through the form and then save it.
For more informations see: https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method
Related
I'm trying to create an "Edit Profile" form in the fronted. What happens is that my form(i'm not 100% sure) tries to create a user instead of finding the current user and update his profile. So I think that's the issue. Checked many questions here but none was clear enough. The fields I'm trying to edit are email(to be checked if email already exisit), Name, user type, and password.
below is the code for forms.py
class ProfileForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('full_name', 'active', 'admin','email','user_type')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(ProfileForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
# user.active = False # send confirmation email
if commit:
user.save()
return user
code for views.py
def profile(request):
user = User.objects.filter(email = request.user)
# form = ProfileForm(user.values().first())
if request.method == 'POST' :
form = ProfileForm(request.POST)
if form.is_valid():
form.save(commit=True)
form = ProfileForm(user.values().first())
# print(user)
context = {
'object_list': user,
'form': form
}
return render(request, 'userpanel/profile.html',context)
Thanks in advance
You didn't pass instance argument to the form. Without instance it will try to create new object. It should be like this:
form = ProfileForm(request.POST, instance=user)
Also you don't need to query user with this: user = User.objects.filter(email = request.user). Just add login_requred decorator to ensure user is authenticated and use request.user:
from django.contrib.auth.decorators import login_required
#login_required
def profile(request):
if request.method == 'POST' :
form = ProfileForm(request.POST, instance=request.user)
I am adding in some functionality that allows a user to edit their personal profile page information. When the user updates their info and hit submit they are getting a NameErrorsaying that the user is not defined. Below is how I am trying to implement the editing functionality.
forms
#this is all the information that the user is allowed to edit.
class UpdateProfile(forms.ModelForm):
username = forms.CharField(required=False)
email = forms.EmailField(required=False)
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
age = forms.IntegerField(required=False)
height = forms.IntegerField(required=False)
weight = forms.IntegerField(required=False)
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'age', 'height', 'weight')
def clean_email(self):
username = self.cleaned_data.get('username')
email = self.cleaned_data.get('email')
if email and User.objects.filter(email=email).exclude(username=username).count():
raise forms.ValidationError('This email address is already in use. Please supply a different email address.')
return email
def save(self, commit=True):
# user = super(RegisterUserForm, self).save(commit=False)
user.email = self.cleaned_data['email']
#This is where i am trying to save the new information.
if commit:
user.save()
#This is where i am returning the user.
return user
Views
def update_profile(request):
args = {}
if request.method == 'POST':
form = UpdateProfile(request.POST, instance=request.user)
form.actual_user = request.user
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('account:profile.html'))
else:
form = UpdateProfile()
args['form'] = form
return render(request, 'account/edit_profile.html', args)
I've searched everywhere for a solution to this problem. Yet, no resolution as of yet.
The problem
After successfully creating a user via a front-end registration form, upon logging in using a front-end login form, the "Authenticate" function returns "None".
The interesting part, if I am to create a new user via the admin panel (using similar code), I am then able to login via the front-end login form.
The custom user model I've created does use an email address as the Username. If a user registers using the front-end register form, the user details are saved to the database, where the password is properly hashed.
Here is the code:
From Forms.py
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import User as CustomUser
from django.conf import settings
class RegisterForm(forms.ModelForm):
password1 = forms.CharField(label='', widget=forms.PasswordInput)
password2 = forms.CharField(label='', widget=forms.PasswordInput)
class Meta:
model = CustomUser
fields = ('email', 'full_name')
def __init__(self, *args, **kwargs):
super(RegisterForm, self).__init__(*args, **kwargs)
self.fields['email'].widget.attrs.update(
{'class': 'form-control loginInput', 'placeholder': 'Your Email (you#company.com)'})
self.fields['full_name'].widget.attrs.update(
{'class': 'form-control loginInput', 'placeholder': 'Your Full Name'})
self.fields['email'].label = ''
self.fields['full_name'].label = ''
self.fields['password1'].widget.attrs.update(
{'class': 'form-control loginInput', 'placeholder': 'Your Password'})
self.fields['password2'].widget.attrs.update(
{'class': 'form-control loginInput', 'placeholder': 'Confirm Password'})
def clean_email(self):
email = self.cleaned_data.get('email')
qs = CustomUser.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Saving the provided password in hashed format
user = super(RegisterForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = CustomUser
fields = ('email',)
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("Passwords don't match")
return password2
def save(self, commit=True):
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
From Views.py
def register(request):
registered = False
if request.method == 'POST':
registration = forms.RegisterForm(data=request.POST)
if registration.is_valid():
member = registration.save()
member.set_password(member.password)
member.save()
registered = True
else:
print(registration.errors)
else:
registration = forms.RegisterForm()
print("Registered: " + str(registered))
return render(request, 'accounts/registration.html',
{'registration_form': registration,
'registered': registered,
})
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect(reverse('account_index'))
else:
HttpResponse("ACCOUNT NOT ACTIVE")
else:
print("Someone tried to login and failed!")
print("Email: {} and password {}".format(username, password))
return HttpResponse("invalid login details supplied!")
else:
return render(request, 'accounts/user_login.html', {})
I'm at a loss at the present time. Could use some direction or advice.
Ok, I've resolved this issue. It seems as though I just needed to sleep on it.
Here is the code that was causing the issue:
In Views.py
member.set_password(member.password)
It seems as if though it was setting a hashed version of the password. But "set_password" must be the raw version of the password.
To fix this I changed it to:
member.set_password(request.POST.get('password1'))
Behold, it works!
I have a UserProfile model to add some things to my User model and one thing I want to do is have unique email for users so I added an email attribute to my UserProfile model and set it to unique=True like this :
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="profile")
email = models.EmailField(unique=True)
avatar = models.ForeignKey(Avatar)
...
I created a custom form for the registration to add some infos directly to my UserProfile :
class CreateUserForm(forms.Form):
username = forms.CharField(max_length=30, label="Pseudo")
password1 = forms.CharField(widget=forms.PasswordInput, label="Password")
password2 = forms.CharField(widget=forms.PasswordInput, label="Confirmez pwd")
email = forms.EmailField(widget=forms.EmailInput, label="E-mail")
avatar = AvatarChoiceField(widget=forms.RadioSelect, queryset=Avatar.objects.all(), label="Avatar")
def clean_username(self):
username = self.cleaned_data.get('username')
if User.objects.filter(username=username).exists():
raise forms.ValidationError("This username is already used")
return username
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 != password2:
raise forms.ValidationError("Your passwords do not match")
return password1
def clean_email(self):
email = self.cleaned_data.get('email')
if UserProfile.objects.filter(email=email).exists():
raise forms.ValidationError("This email is already used")
return email
And then in my views.py I treat my form like that :
def create_user(request):
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
username = form.clean_username()
email = form.clean_email()
password = form.clean_password2()
username = form.cleaned_data['username']
avatar = form.cleaned_data['avatar']
user = User.objects.create_user(username=username, password=password)
user.save()
user_profile = UserProfile(user=user, email=email, avatar=avatar)
user_profile.save()
else:
form = CreateUserForm()
return render(request, 'accounts/create.html', locals())
Finally I used the email of the form for my UserProfile model and not for my User model. And by this way I have a unique email for my users. And it's working.
Am I doing it right or is there a better way to achieve what I want ?
You are on the right track, the only thing that doesn't look right is that you shouldn't call clean method manually like this:
# These are not needed in your view method
username = form.clean_username()
email = form.clean_email()
password = form.clean_password2()
They are already called by form.is_valid(). See this SO question for details.
I'm trying to create edit user profile functionality. But I get the following error
Traceback:
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/views.py" in update_profile
60. form.save()
File "/forms.py" in save
108. user = super(UserUpdateForm, self).save(commit=False)
Exception Type: AttributeError at /editseekerprofile/
Exception Value: 'super' object has no attribute 'save'
Here is my views.py
def update_profile(request):
args = {}
if request.method == 'POST':
form = UserUpdateForm(request.POST)
if form.is_valid():
form.save()
return render(request,'meddy1/seekerprofile.html',{'doctorSeeker': profile})
else:
form = UserUpdateForm()
args['form'] = form
return render(request, 'meddy1/editseekerprofile.html', args)
Here is my forms.py
class UserUpdateForm(forms.Form):
name = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'FirstName LastName'}))
email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Please enter a valid email address so we can reach you. No spam. Ever.'}))
password1 = forms.CharField(label="Old Password",widget=forms.PasswordInput(attrs={'class': 'form-control','placeholder':'Enter your password to save the changes.'}),required=False)
password2 = forms.CharField(label="New Password?",widget=forms.PasswordInput(attrs={'class': 'form-control','placeholder':'Only enter new password if you want to change it.'}),required=False)
password3 = forms.CharField(label="Confirm New Password",widget=forms.PasswordInput(attrs={'class': 'form-control','placeholder':'Confirm New Password'}),required=False)
class Meta:
model = DoctorSeeker
fields = ("name","email")
class Meta:
model = User
fields = ("password2", "password3")
def clean_password2(self):
password2 = self.cleaned_data.get("password2")
password3 = self.cleaned_data.get("password3")
if password2 and password3 and password2 != password3:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def save(self, commit=True):
user = super(UserUpdateForm, self).save(commit=False)
user.set_password(self.cleaned_data["password2"])
fullName = self.cleaned_data["name"]
Email = self.cleaned_data["email"]
if commit:
user.save()
userProfile = DoctorSeeker(user=user, name=fullName, email=Email)
userProfile.save()
return user
Just to clarify, I'm saving user information in two different models, one is the default user model and the other one is DoctorSeeker.
forms.Form has no method called save, thats why you can't override it. forms.ModelForm has the save method which you can override.