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)
Related
I'm trying to create a website with a log in and registration form in django, the registration works well, it saves the accounts in the database, but when I try to log in, it doesn't work at all, here's the code:
views.py
from django.shortcuts import render
from .forms import UserForm
from django.contrib.auth import authenticate, login, logout
from django.urls import reverse
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponse
# Create your views here.
def index(request):
return render(request, 'app1/index.html')
#login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect(reverse('index'))
def register(request):
registered = False
if request.method == "POST":
user_form = UserForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserForm()
return render(request, 'app1/register.html',{'user_form':user_form, '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:
if user.is_active:
login(request, username)
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse("Account Not Active")
else:
print("Someone tried to login and failed")
print(f"Username: {username} and password {password}")
return HttpResponse ("Invalid Login details supplied")
else:
return render(request, 'app1/login.html')
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserForm(UserCreationForm):
email = forms.EmailField(max_length=40, help_text='Required')
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
I hope that someone could help me because I believe that the error is in the views.py, but I'm not sure where.
in login function we have to pass user not username so in user_login function
if user:
if user.is_active:
login(request, user)
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse("Account Not Active")
A UserCreationForm already hashes the password by calling set_password, hence calling it a second time, will double hash it. You thus should remove the user.set_password(user.password) line:
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
if user_form.is_valid():
# do not hash a second time
# user.set_password(user.password)
user = user_form.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserForm()
return render(request, 'app1/register.html',{'user_form':user_form, 'registered':registered})
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
With gracious help from another member on here, I am using a customized backend that checks for two requirements to log someone in.
backends.py
from django.contrib.auth.backends import ModelBackend
class ProfileCheckBackend(ModelBackend):
def user_can_authenticate(self, user):
is_active = super().user_can_authenticate(user)
return is_active and getattr(user.profile, "approved", False)
settings.py
AUTHENTICATION_BACKENDS = [
"django_site.backends.ProfileCheckBackend",
# "django.contrib.auth.backends.ModelBackend"
]
This works great, but when a user tries to sign up, they need to be logged in to move to the next function:
views.py
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
user_object = form.save()
user_object.is_active = True
user_object.save()
username = form.cleaned_data.get('username')
password = make_password(form.cleaned_data.get('password1'))
# user = authenticate(username=username, password=password)
user = form.save()
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
# messages.success(request, f'Your account has been created! You are now able to log in!')
return redirect('sign_up_post')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
#login_required()
def sign_up_post(request):
if request.method == 'POST':
...
The login function, however, does not log the user in. How can I fix this?
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})
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