I have added python-social-auth in my project for social logins. I also have a signup form of my own for new users. For social logins, I added some authentication backends.
Now, the social logins are working fine, but the signup form causes some problems.
After I enter the details, and click signup, this error comes up.
I see in the admin panel, the user was added even after this error.
ValueError: You have multiple authentication backends configured and therefore must provide the `backend` argument or set the `backend` attribute on the user.
Now, it is asking me to set the backend attribute of the user. How to set that ?
Here is the view for signup,
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_pass = form.cleaned_data.get('password')
user = authenticate(username=username,password=raw_pass)
login(request,user)
return redirect('location:get_location')
else:
form = SignupForm()
return render(request, 'signup.html', {'form':form})
Worked for me:
if request.method == 'POST':
form = UserCreateForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
return redirect('/')
else:
pass
Related
this is my blog : http://gorani-dncvb.run.goorm.io/
I am trying to build a signup page for my django blog.
I finished writing codes for template/view/form/url, and successfully connected to the page : http://gorani-dncvb.run.goorm.io/accounts/signup.
So I came to think there is no problem in template/url. but the problem arises after trying signup, It saids :
IntegrityError at /accounts/signup
UNIQUE constraint failed: auth_user.username
and this is my view code :
def signup(request):
if request.method == "POST":
form = SignupForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password')
user = User.objects.create_user(username=username, password=raw_password)
return redirect("post_list")
else:
form = SignupForm()
return render(request, 'registration/signup.html', {'form':form})
and this is form code :
class SignupForm(forms.ModelForm):
class Meta:
model = User
fields = ('username','password',)
(I didn't used UserCreateForm on purpose)
There's definitely no overlapping another user, so why I'm seeing this error message?
The reason for duplicating the user is that django creates the user when saving the form.
When a form is a child of ModelForm, saving it will create a new object of the model class related to the form.
Just delete or comment the code lines for user creation and it wil work fine:
def signup(request):
if request.method == "POST":
form = SignupForm(request.POST)
if form.is_valid():
user = form.save()
user.set_password(user.password)
user.save()
return redirect("post_list")
else:
form = SignupForm()
return render(request, 'registration/signup.html', {'form':form})
Best regards.
I'm trying to get users automatically logged in after registration. However the user only seems to be logged in for the duration of rendering the next html page (user.is_authenticated returns True in my templates) and gets logged out immediatly after (request.user returns AnonymousUser in a method I call via AJAX on the next page - moving to another page also makes clear you are not logged in anymore since my templates render the login instead of the logout links again). If I try the commented code instead authenticate() always returns NONE.
What am I doing wrong?
def signup_view(request):
if request.method == 'POST':
form = UserSignUpForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
send_confirmation_email(user, current_site.domain)
# user_login = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password1'])
# login(request, user_login)
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
args = {'user': user}
return render(request, 'accounts/signup_success.html', args)
else:
form = UserSignUpForm()
args = {'form': form, 'project_name': settings.PROJECT_NAME}
return render(request, 'accounts/signup.html', args)
Please use following lines of code. It may full fill your requirements.
def signup(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('records:dashboard')
else:
form = UserCreationForm()
return render(request, 'registration/signup.html', {'form': form})
I am trying to make a page that registers users and then logs them in immediately after. It then redirects them to their profile which is a url that contains their id. There is a model called person, and it has a one-to-one field with User. This is the code for my post method (when someone fills out the register form).
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit = False)
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
newperson = person(user=user)
newperson.save()
user.save()
if user is not None:
if user.is_active:
login(request, user)
return redirect('/profiles/' + str(user.person.id))
return render(request, self.template_name, {'form': form})
It then runs this function:
def loadprof(request, profile_id):
print(request.user)
try:
user = person.objects.get(id=profile_id)
user_schedules = user.schedules_set.all()
except person.DoesNotExist:
raise Http404("The profile you are looking for does not exist.")
if request.user.person.id == profile_id:
return render(request, 'profile.html', {'user': user,
"user_schedules": user_schedules})
return render(request, 'profile.html', {'user': user, "user_schedules":
user_schedules})
It raises a 'AnonymousUser' object has no attribute 'person' error when it runs "if request.user.person.id == profile_id:" in the loadprof function. What is happening? I assume because it is an AnonymousUser, the login function didn't work? I imported the login function correctly and everything, I am very lost. Thank You
I'm pretty new to Python.
My problem is that I want to restrict users who are already logged in from being able to visit the log in and sign up pages.
Essentially, what I'm looking for is something like the #login_required decorator, that will allow access to these pages for users who are not logged in.
So far, I have
Looked at other SO questions such as Django-Registration: How to prevent logged in user from registering?, however I've tried the solution here, and it does not work for me.
I've searched through the Django Documentation, Django Girls and other websites that offer tutorials for learning Django.
Here's my views.py for the log in:
def login_view(request): # Login View to begin user session
print(request.user.is_authenticated())
if request.method == 'POST':
form = UserLogInForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
print(request.user.is_authenticated())
return HttpResponseRedirect('/')
else:
form = UserLogInForm()
return render(request, 'login.html', {'form': form})
else:
form = UserLogInForm()
return render(request, 'login.html', {'form': form})
and the sign up:
class signup_view(View):
form_class = UserSignUpForm
template_name = 'signup.html'
# Blank form is requested
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
# Form is filled in and posted to DB - Process the Data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
# Further checks before committing object to the DB
# Cleaned Data
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
email = form.cleaned_data['email']
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = User.objects.create_user(first_name=first_name,
last_name=last_name,
email=email,
username=username,
password=password
)
user.set_password(password)
user.save()
user = authenticate(email=email, username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/')
return render(request, self.template_name, {'form': form})
If anybody knows any solutions then that would be amazing, thank you.
Since you are using a class-based view, you can use the UserPassesTestMixin and in the check method test that the user is anonymous:
class signup_view(UserPassesTestMixin, View):
...
def test_func(self):
return self.request.user.is_anonymous()
You can do a similar thing for the other view using the #user_passes_test decorator.
i guess you can add a middleware something like this :
your_app/middlewares/user_restriction_middleware.py
and that files be like:
class UserRestrictionMiddleware:
def process_request(self, request):
if request.user.is_authenticated():
request_path = request.path_info
if request_path.startswith('/login/') or request_path.startswith('/register/') :
return HttpResponseRedirect('.... to whereever you want...')
add this to your settings.py's MIDDLEWARE_CLASSES like :
'your_app.middlewares.user_restriction_middleware.UserRestrictionMiddleware',
Add this code before the POST request form .
class login(request):
if request.user.is_authenticated:
return redirect('app_name_space_name:your_url_name_to_send_authenticated_user_to')
#Your codes here
I am having an issue with Django users changing passwords - I have built a few production sites in Django, just none in about a year (or in 1.8), but I don't recall having this issue before.
Summary
When a user changes their password, the user is logged out, but the password is successfully changed.
Details
I have a view that allows a user to change a password, I am using standard django forms and the auth framework, and to stress: changing the password works, it just logs the user out so that they have to login again.
I actually don't mind this terribly, I would prefer that the user be redirected to their dashboard with a message update, if i need to reauth the user in the code, then I will, just seems kind of clunky.
here is my view function:
#login_required
def user_change_password(request):
"""Allows a user to change their password"""
if request.method == "POST":
form = SubscriberPasswordForm(request.POST)
if form.is_valid():
try:
request.user.set_password(form.cleaned_data['password'])
request.user.save()
except Exception, err:
print "Error changing password: {}".format(err)
messages.add_message(request, messages.ERROR, 'The password could not be changed, please try again '
'later. This admins have been notified of this error.')
else:
#this outputs True
print request.user.is_authenticated()
messages.add_message(request, messages.INFO, 'Your password has been changed successfully')
return HttpResponseRedirect("/accounts/dashboard/")
else:
form = SubscriberPasswordForm()
return render(request, "accounts/change-password.html", {"form": form})
So the password is changed, the user gets redirected to the dashboard page, the #login_required decorator then redirects them back to the login screen.
The password form is here, though it is pretty straightforward.
class SubscriberPasswordForm(forms.Form):
password = forms.CharField(widget=forms.PasswordInput)
cpassword = forms.CharField(widget=forms.PasswordInput)
def clean_cpassword(self):
password1 = self.cleaned_data.get("password")
password2 = self.cleaned_data.get("cpassword")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
For django 1.9:
from django.contrib.auth import update_session_auth_hash
def password_change(request):
if request.method == 'POST':
form = PasswordChangeForm(user=request.user, data=request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
The following fields must be supplied in the POST request:
old_password
new_password1
new_password2
See detailed docs at update_session_auth_hash
My understanding is being logged out after password change is new in Django 1.7. So you will need to re-auth user in your code as you said.
See Release Notes:
https://docs.djangoproject.com/en/1.8/releases/1.7/#django-contrib-auth
Here is the specific note:
"The AbstractBaseUser.get_session_auth_hash() method was added and if your AUTH_USER_MODEL inherits from AbstractBaseUser, changing a user’s password now invalidates old sessions if the SessionAuthenticationMiddleware is enabled. See Session invalidation on password change for more details including upgrade considerations when enabling this new middleware."
See Documentation:
https://docs.djangoproject.com/en/1.7/topics/auth/default/#session-invalidation-on-password-change
For Django 1.8
Simply call update_session_auth_hash after set_password like so:
from django.contrib.auth import update_session_auth_hash
request.user.set_password(form.cleaned_data['password'])
update_session_auth_hash(request, request.user)
for Django 3, Django 1.8+ use this link:
https://docs.djangoproject.com/en/3.2/topics/auth/default/#django.contrib.auth.update_session_auth_hash
or use this code:
from django.contrib.auth import update_session_auth_hash
def password_change(request):
if request.method == 'POST':
form = PasswordChangeForm(user=request.user, data=request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
else:
...