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.
Related
Working on a sign up form, and when all inputs are submitted, the user is correctly populated in database, but the web page is generating the following error:
AttributeError at /accounts/sign_up/
'User' object has no attribute 'backend'
i've searched for the last hour but can't figure what this issue might be
i don't see any backend declared in settings, but i thought that this was automatically set with built in Django Auth?
Anyways here is my stack trace:
Traceback:
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py" in get_response
149. response = self.process_exception_by_middleware(e, request)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py" in get_response
147. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\crstu\Desktop\JSPROJ\dealmazing\accounts\views.py" in sign_up
55. login(request, user)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\contrib\auth\__init__.py" in login
112. request.session[BACKEND_SESSION_KEY] = user.backend
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\utils\functional.py" in inner
205. return func(self._wrapped, *args)
Exception Type: AttributeError at /accounts/sign_up/
Exception Value: 'User' object has no attribute 'backend'
which appears to be pointing back to my sign_up view here:
def sign_up(request):
form = forms.UserCreateForm()
if request.method == 'POST':
form = forms.UserCreateForm(data=request.POST)
if form.is_valid():
form.save()
user = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email = form.cleaned_data['email']
)
login(request, user)
messages.success(
request,
"You're now a user! You've been signed in, too."
)
return HttpResponseRedirect(reverse('home')) # TODO: go to profile
return render(request, 'accounts/sign_up.html', {'form': form})
and here is my custom UserCreateForm:
class UserCreateForm(UserCreationForm):
"""Form for creating a new user."""
verify_email = forms.EmailField(label="Please verify your email address.")
class Meta:
fields = [
'username',
'email',
'verify_email',
'password1',
'password2'
]
model = get_user_model()
def clean(self):
data = self.cleaned_data
email = data.get('email')
verify = data.get('verify_email')
if email != verify:
raise forms.ValidationError(
"You need to enter the same email in both fields"
)
return data
and my custom User model:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, default='')
date_joined = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return "#{}".format(self.username)
def get_short_name(self):
return self.username
def get_long_name(self):
return "#{} ({})".format(self.username, self.email)
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'm using a view to create new users in Django. And then I have another view to log them in.
But when I create a user, and I try to log in with authenticate(username=username_post, password=password_post), I get None, so it displays in the template 'Wrong username or password.'.
In my database, I see new registers every time I create a new user. However, as the password is encrypted, I can't say if the problem is the login view, or the register view.
However, the super user that I created through the command line after I first installed django, is able to login with no problem, so that makes me thing that the problem is when I create the user.
These are my Login and Register views:
class Login(View):
form = LoginForm()
message = None
template = 'settings/blog_login.html'
def get(self, request, *args, **kwargs):
if request.user.is_authenticated():
return redirect('settings:index')
return render(request, self.template, self.get_context())
def post(self, request, *args, **kwargs):
username_post = request.POST['username']
password_post = request.POST['password']
user = authenticate(username=username_post, password=password_post)
if user is not None:
login(request, user)
return redirect('settings:index')
else:
self.message = 'Wrong username or password.'
return render(request, self.template, self.get_context())
def get_context(self):
return {'form': self.form, 'message': self.message}
class Register(CreateView):
success_url = reverse_lazy('settings:login')
model = User
template_name = 'settings/blog_register.html'
form_class = RegisterForm
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.set_password(self.object.password)
self.object.save()
return HttpResponseRedirect(self.get_success_url())
And these are my forms:
class LoginForm(forms.Form):
username = forms.CharField(max_length=20, label='Username')
password = forms.CharField(label='Password', widget=forms.PasswordInput())
class RegisterForm(forms.ModelForm):
username = forms.CharField(max_length=20, label='Username')
password1 = forms.CharField(label='Password', widget=forms.PasswordInput(),
error_messages={'required': 'Required field.',
'unique': 'Username already used.',
'invalid': 'Not valid username.'})
password2 = forms.CharField(label='Retype password', widget=forms.PasswordInput(),
error_messages={'required': 'Required field.'})
email = forms.EmailField(error_messages={'required': 'Required field.',
'invalid': 'Invalid email.'})
def clean(self):
clean_data = super(RegisterForm, self).clean()
password1 = clean_data.get('password1')
password2 = clean_data.get('password2')
if password1 != password2:
raise forms.ValidationError('Passwords are different.')
return self.cleaned_data
def clean_email(self):
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(
username=username).exists():
raise forms.ValidationError('Email already used.')
return email
class Meta:
model = User
fields = ('username', 'password1', 'password2', 'email')
Please, let me know if you need more info.
You don't have a field called 'password' in your form - you just have 'password1' and 'password2' - so nothing is saved to the model object's actual password field. So, when you do self.object.set_password(self.object.password), you're actually setting a blank password.
Instead, you should get the value from your form's password1 field:
self.object.set_password(self.form.cleaned_data['password1'])
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
I'm trying to create a simple user registration in Django and I get this error. I've looked it up here on stackoverflow: 'AnonymousUser' object has no attribute 'backend', Django Register Form 'AnonymousUser' object has no attribute 'backend' and tried calling authentication before login. But I keep getting this error.
Can anyone please help me with this?
Here is the traceback
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 "/Library/Python/2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
57. return view_func(*args, **kwargs)
File "/Users/harisaghadi/Dropbox/Senior Project/Django Tutorials/mysite/meddy1/views.py" in signup_user
51. login(request, new_user)
File "/Library/Python/2.7/site-packages/django/contrib/auth/__init__.py" in login
85. request.session[BACKEND_SESSION_KEY] = user.backend
File "/Library/Python/2.7/site-packages/django/utils/functional.py" in inner
214. return func(self._wrapped, *args)
Exception Type: AttributeError at /meddy1/signup/
Exception Value: 'AnonymousUser' object has no attribute 'backend'
Here is my forms.py
class UserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username and
password.
"""
error_messages = {
'duplicate_username': _("A user with that username already exists."),
'password_mismatch': _("The two password fields didn't match."),
}
email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Please enter a valid email address so we can reach you.'}))
username = forms.RegexField(label=_("Username"), max_length=30,
regex=r'^[\w.#+-]+$',
help_text=_("Required. 30 characters or fewer. Letters, digits and "
"#/./+/-/_ only."),
error_messages={
'invalid': _("This value may contain only letters, numbers and "
"#/./+/-/_ characters.")})
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_username(self):
# Since User.username is unique, this check is redundant,
# but it sets a nicer error message than the ORM. See #13147.
username = self.cleaned_data["username"]
try:
User._default_manager.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(
self.error_messages['duplicate_username'],
code='duplicate_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(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
userProfile = DoctorSeeker(user=user, name=name, email=email)
userProfile.save()
return user
views.py
def index(request):
return HttpResponse("Welcome to Meddy")
# -------------------- Authentication ----------------------
def signup(request):
return render(request, 'meddy1/signup.html', {})
#csrf_exempt
def signup_user(request):
if request.method == 'POST':
form = UserCreationForm(request.POST,request.FILES)
if form.is_valid():
new_user = authenticate(username=request.POST['username'],password=request.POST['password1'])
login(request, new_user)
return HttpResponseRedirect(reverse('index'))
else:
form = UserCreationForm()
return render(request, "meddy1/signup.html", {'form': form,'usersignup':True})
def login_user(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username,password=password)
if user:
return render(request, 'meddy1/index.html')
else:
return HttpResponseRedirect('/')
def logout_user(request):
logout(request)
return HttpResponseRedirect('/')
models.py
class DoctorSeeker(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField()
user = models.ForeignKey(User, unique=True)
def __unicode__(self):
return u"%s %s" % (self.name, self.email)
Since you found the similar posts, i take it, you understand, that your authenticate does not really authenticate anything. It fails for some reason.
I understand that the view you are showing us is trying to accomplish 2 things- create user and log him in? Right? Since its name is signup_user.
Well. You have UserCreationForm, but you do not save it. So you cant really authenticate an user, that does not yet exist in the system. Save your form first, then call authenticate.