I have a custom user model. After doing successful login, I am getting the anonymous user in HttpResponseRedirect and templates as well. How do I get the logged in user?
Login View:
class LoginFormView(View):
form_class = UserLoginForm
user_model = get_user_model()
template_name = 'account/login.html'
def get(self, request, *args, **kwargs):
form = self.form_class
return render(request, self.template_name, {'form':form})
def post(self, request, *args, **kwargs):
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect(reverse('home'))
else:
messages.error(request, 'Please enter correct email and password!')
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
If you have the request template context processor enabled, you'll be able to access the user in the template with {{ request.user}}.
Secondly, make sure you are importing the login function and not the login view. It should be:
from django.contrib.auth import login
Related
Why when i desactive user on Django admin site in my class in post method
requirement return negative first if requirement user is not None ?
Probably if user desative true Django don`t look him in user table ?
class LoginView(View):
template_name = 'login.html'
def get(self, request):
form = LoginForm()
return render(request, self.template_name, locals())
def post(self, request):
form = LoginForm(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:
if user.is_active:
login(request, user)
return redirect('home')
else:
alert = messages.error(request, 'Twoje konto zostało zablokowane!')
return render(request, self.template_name, locals())
else:
alert = messages.error(request, 'Błędna nazwa użytkownika!')
return render(request, self.template_name, locals())
In authenticate function, django call authenticate on your AUTHENTICATION_BACKENDS in settings.py.
ModelBackend is a default authentication backend that has been provided by Django, and if you are using it, it checks if user is acive or not. It's sth like this:
def user_can_authenticate(self, user):
"""
Reject users with is_active=False. Custom user models that don't have
that attribute are allowed.
"""
is_active = getattr(user, 'is_active', None)
return is_active or is_active is None
I've made a user model with USERNAME_FIELD defined as phone_number. So login form requires phone_number and password. I want users to be able to also login through their emails. So I created an authentication backend class. Users can login with their phone numbers but they canbot do so with their emails and will receive the 'Username and/or password is wrong' message.
authentication.py:
from django.contrib.auth import get_user_model
class CustomAuthBackend:
def authenticate(self, username=None, password=None):
try:
user = get_user_model().objects.get(email=username)
if password:
if user.check_password(password):
return user
return None
except:
return None
def get_user(self, user_id):
try:
user = get_user_model().objects.get(pk=user_id)
return user
except:
return None
forms.py:
class UserLoginForm(forms.Form):
username = forms.CharField(label="Phone Number / Email")
password = forms.CharField(widget=forms.PasswordInput(), label="Password")
views.py:
class UserLogin(View):
form_class = UserLoginForm
template_name = "accounts/login.html"
def get(self, request):
return render(request, self.template_name, {"form": self.form_class})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(
request, username=cd["username"], password=cd["password"]
)
if user:
login(request, user)
messages.success(request, "Logged in successfully.", "success")
return redirect("home:home")
else:
messages.error(request, "Username and/or password is wrong.", "danger")
return render(request, self.template_name, {"form": form})
messages.error(request, "Login failed", "danger")
return render(request, self.template_name, {"form": form})
settings.py:
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"accounts.authentication.CustomAuthBackend",
]
Assuming that you have already included the custom backend in AUTHENTICATION_BACKENDS setting in settings.py file.
You can make a condition check that whether it is a phone no. or email using regex so:
import re
from django.contrib.auth import get_user_model
class CustomAuthBackend:
def authenticate(self, request, username=None, password=None):
UserModel = get_user_model()
# Check whether username is an email address or phone number
if re.match(r'^\+?\d{10,14}$', username):
try:
user = UserModel.objects.get(phone_number=username)
if user.check_password(password):
return user
except UserModel.DoesNotExist:
return None
else:
try:
user = UserModel.objects.get(email=username)
if user.check_password(password):
return user
except UserModel.DoesNotExist:
return None
def get_user(self, user_id):
try:
return get_user_model().objects.get(pk=user_id)
except get_user_model().DoesNotExist:
return None
I had forgotten to include request as a parameter in authenticate method. :)
Correct version:
def authenticate(self, request, username=None, password=None):
# ...
I creating quiz app, in which user login with only username and the proceed for a quiz but django authenticate not working
views.py
class UserFormView(View):
form_class = UserForm
template_name = 'app/registration_form.html'
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)
# cleaned data
username = form.cleaned_data['username']
user.save()
# autheticate
user = authenticate(username=username)
if user is not None:
if user.is_active:
login(request, user)
return redirect('app:quiz_list')
else:
return HttpResponse('active nahi hai')
else:
return HttpResponse('pehchan me nahi hai')
return render(request, self.template_name, {'form': form})
If you are using default authentication backend it requires username and password
You can create a custom authentication backend yourself by following related documentation
Considering you are not really authenticating you can just filter user from database and use login function afterwards
#TODO add exception if there is no user with username
user = User.objects.filter(username=username).get()
login(request, user)
I'm Prety new in Django. After a few google search, I find full CRUD and I know how to handle that. But in User registration, I fell some problem all over the online every one uses Form.py to handle registration form but I don't want to use Form.py I like to customize it.
but the problem is when I use auth for login then Django auth says it's a wrong password
I use
authenticate(email=email,password=password)
for login check
Is anyone please explain custom login registration without using Form.py with some example.
Here is my View.py Code
def loginCheck(request):
if request.method == 'POST':
username = request.POST.get('username'),
password = request.POST.get('password'),
user = authenticate(request, username=username, password=password)
if user is not None:
return HttpResponse('Find User')
else:
return HttpResponse("Not Find User")
and my User Registration Code
def registration(request):
checkData = AuthUser.objects.filter(email=request.POST.get('email'))
if not checkData:
User.objects.create_user(
username=request.POST.get('username'),
email=request.POST.get('email'),
password=(request.POST.get('password')),
)
messages.add_message(request, messages.INFO, 'User Saved Successfully')
return redirect('loginView')
else:
messages.add_message(request, messages.INFO, 'Email Already Exists')
return redirect('loginView')
My Login code return Not Find User.
Try this minimal example. In this, you can create User and log in through API.
import json
from django.views.generic import View
from django.contrib.auth.models import User
from django.http import JsonResponse
from django.contrib.auth import authenticate, login
class UserRegisterView(View):
def get(self, request):
return JsonResponse({"message": "METHOD NOT ALLOWED"})
def post(self, request, *args, **kwargs):
json_body = json.loads(request.body)
username = json_body.get('username')
password = json_body.get('password')
email = json_body.get('email')
is_staff = json_body.get('is_staff', False)
is_superuser = json_body.get('is_superuser', False)
User.objects.create_user(
username=username, email=email,
password=password, is_staff=is_staff,
is_superuser=is_superuser
)
return JsonResponse({"message": "User created"})
class LoginView(View):
def get(self, request):
return JsonResponse({"message": "METHOD NOT ALLOWED"})
def post(self, request, *args, **kwargs):
'''
input data format:
{
"username" : "my username",
"password":"mysecret123#"
}
'''
json_body = json.loads(request.body)
username = json_body.get('username')
password = json_body.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return JsonResponse({"message": "login success"})
else:
return JsonResponse({"message": "login failed"})
Why I parsed request.body ?
How to receive json data using HTTP POST request in DJANGO
Reference:
How to authenticate user in DJANGO (official-doc)
UPDAYE-1
updated view as per the request,checking sufficent data in POST method (bold code)
def loginCheck(request):
if request.method == 'POST' and 'username' in request.POST and 'password' in request.POST:
username = request.POST.get('username'),
password = request.POST.get('password'),
user = authenticate(request, username=username, password=password)
if user is not None:
return HttpResponse('Find User')
else:
return HttpResponse("Not Find User")
return HttpResponse("POST data wrong")
If you want to your own registration process, you must use set_password function for saving password.
from django.contrib.auth.models import User
user = User.objects.get_or_create(username='john')
user.set_password('new password')
user.save()
The django usermodel django.contrib.auth.models.User has a field 'last_login' record the time when a user is successfully login.
But I donot see a code such as 'last_login=datetime.now()' in function from django.contrib.auth import login or from django.contrib.auth import authenticate. I also checked the django.contrib.auth.signals.user_logged_in.
where is the code for update the field 'last_login'?
Below is all the related source coede,how is the login process invoke the update_last_login? I don't see any code in login views or Authenticate function suoure code.
def update_last_login(sender, user, **kwargs):
"""
A signal receiver which updates the last_login date for
the user logging in.
"""
user.last_login = timezone.now()
user.save(update_fields=['last_login'])
user_logged_in.connect(update_last_login)
from django.dispatch import Signal
user_logged_in = Signal(providing_args=['request', 'user'])
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
"""
Displays the login form and handles the login action.
"""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(request, data=request.POST)
if form.is_valid():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
current_site = get_current_site(request)
context = {
'form': form,
redirect_field_name: redirect_to,
'site': current_site,
'site_name': current_site.name,
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
class ModelBackend(object):
"""
Authenticates against settings.AUTH_USER_MODEL.
"""
def authenticate(self, username=None, password=None, **kwargs):
UserModel = get_user_model()
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
try:
user = UserModel._default_manager.get_by_natural_key(username)
if user.check_password(password):
return user
except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a non-existing user (#20760).
UserModel().set_password(password)
user_logged_in signal is connected to django.contrib.auth.models.update_last_login function, it makes:
user.last_login = timezone.now()
user.save(update_fields=['last_login'])
I think the best way of doing this thing is
request_user, data = requests.get_parameters(request)
user = requests.get_user_by_username(data['username'])
update_last_login(None, user)
You can also get user for request object by doing following.
user = request.user
on djnago 1.11
add this class :
class IsAuthenticated(BasePermission):
"""
Allows access only to authenticated users.
"""
def has_permission(self, request, view):
if request.user and request.user.is_authenticated:
user = request.user
user.last_login = timezone.now()
user.save(update_fields=['last_login'])
return request.user and request.user.is_authenticated
on setting file change :
'DEFAULT_PERMISSION_CLASSES': (
# custom class
'IsAuthenticated',
),