I am trying to use the default Django from django.contrib.auth authenticate() method to authenticate if the user exists. I am doing this right after the user registers. The user registers and their username, email, and password is inputted into the database, but when I call authenticate(username=username, password=password) it is returning None for some reason. The password is being stored as a hash and it is worth to note that I am using my own custom User model, but inheriting from django.contrib.auth User model.
Here's my view:
class RegisterView(SuccessMessageMixin, View):
form_class = RegisterForm
template_name = 'oauth/auth_form.html'
success_message = "You have successfully created an account!"
# Display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False) # Do not save to table yet
username = form.cleaned_data['username']
password = form.cleaned_data['password']
try:
validate_password(password, user)
except ValidationError as e:
form.add_error('password', e) # to be displayed with the field's errors
return render(request, self.template_name, {'form': form})
user.set_password(password)
user.save()
# Let's try to login the user
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('http://google.com')
return render(request, self.template_name, {'form': form})
Why is it that the authenticate method is not working out for me?
Although #schwobaseggl 's answer should solve your issue, i.e. "No need to authenticate, just login directly", I've done something very similar in one of my older projects and maybe it helps you.
Here the registration process automatically logged in the user, and we were using email tokens as password:
def get_or_create_user(mobile):
UserModel = get_user_model()
try:
user = UserModel.objects.get(mobile=mobile)
except UserModel.DoesNotExist:
user = UserModel(mobile=mobile, username=mobile)
user.set_unusable_password()
user.save()
return user
...
class UserRegistrationAndLogin(View):
...
def post(self, request):
form = self.form_class(request.POST)
next_url = request.GET.get('next')
if form.is_valid():
entered_token = form.cleaned_data['otp']
if entered_token == self.token:
user = get_or_create_user(mobile=self.mobile)
login(request, user)
return redirect(next_url or settings.LOGIN_REDIRECT_URL)
else:
form.add_error('otp', 'OTP does not match!')
return render(request, self.template_name, context={'form': form, 'mobile': self.mobile})
Related
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 using my own custom User model, but I'm inheriting off of django.contrib.auth User model. I have a username, email, and password field. I don't explicitly add the password field because it gets added by default by the inheritance. When I try to create a superuser through the command line, the normal default Django password validation is working correctly. However, when I have a sign up form, it is not. Email and username validation are working properly when I click submit, but there is no password validation. I can enter whatever I want and it would accept the password.
Here's my forms.py
class RegisterForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'email', 'password']
username = forms.CharField(label='Username', widget=forms.TextInput(attrs={'placeholder': 'Username:'}))
email = forms.EmailField(label='Email', widget=forms.EmailInput(attrs={'placeholder': 'Email:'}))
password = forms.CharField(label='Password', widget=forms.PasswordInput(attrs={'placeholder': 'Password:'}))
Here's my view:
class RegisterView(SuccessMessageMixin, View):
form_class = RegisterForm
template_name = 'oauth/auth_form.html'
success_message = "You have successfully created an account!"
# Display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False) # Do not save to table yet
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
# Let's try to login the user
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('profiles: index')
return render(request, self.template_name, {'form': form})
How can I make it so that the password field gets validated correctly with the default password validation from Django?
Django has some utils to integrate password validation. The easiest would be to call the validate_password function in the field specific clean_password method of the form, but since you need a user instance for some validators, I shall demonstrate its use in the view:
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
class RegisterView(SuccessMessageMixin, View):
# ...
def post(self, request):
if form.is_valid():
user = form.save(commit=False) # Do not save to table yet
username = form.cleaned_data['username']
password = form.cleaned_data['password']
try:
validate_password(password, user)
except ValidationError as e:
form.add_error('password', e) # to be displayed with the field's errors
return render(request, self.template_name, {'form': form})
# ...
return render(request, self.template_name, {'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 have a problem with the method Login(), the variable 'user' if it contains the user but that method fails. could help detect the problem.
from django.contrib.auth import authenticate, login
def login(request):
if request.user.is_authenticated():
return render(request, 'Default.html')
mensaje = ''
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
User = authenticate(username=username, password=password)
if User is not None:
if User.is_active:
login(User)
return render(request, 'Default.html')
else:
return render(request, 'accounts/login.html', {'mensaje':mensaje})
else:
return render(request, 'accounts/login.html', {'mensaje':mensaje})
You are importing login from django.contrib.auth but look at your very next line of code.
from django.contrib.auth import authenticate, login
def login(request):
if request.user.is_authenticated():
return render(request, 'Default.html')
Yep, you are shadowing that login method with one for your own. The solution would be to rename your own funciton
def my_login(request):
if request.user.is_authenticated():
return render(request, 'Default.html')
Also, according to the documentation, login() function expects 2 arguments to be passed in - a request instance and a user model instance:
login(request, User)