Django empty error messages - django

I have an ajax login view. I can log in ok but when I log in incorrectly my json returns:
{"errors": {}}
My view is as follows:
def ajaxlogin(request):
from forms import LoginForm
form = LoginForm(request.POST)
logged_in = False
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if request.is_ajax() and user is not None:
login(request, user)
logged_in = True
return HttpResponse(simplejson.dumps({'redirect' : 'true'}), content_type='application/json')
else:
return HttpResponse(simplejson.dumps({'errors': dict(form.errors.items())}), content_type='application/json')
Any ideas?
If I use the login function without js enabled the form displays all the relevant error messages.
My LoginForm:
from django import forms
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import authenticate
from django.utils.translation import ugettext_lazy as _
class LoginForm(AuthenticationForm):
username = forms.CharField(min_length=5, max_length=30,error_messages={'required':_("please enter a username"), 'min_length':_("username must be at least 5 characters"), 'max_length':_("username must be at less than 30 characters")})
password = forms.CharField(min_length=6, error_messages={'required':_("please enter a password"), 'min_length':_("password must be at least 6 characters")})
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(username=username, password=password)
if self.user_cache is None:
raise forms.ValidationError(_("you have entered an incorrect username and/or password"))
elif not self.user_cache.is_active:
raise forms.ValidationError(_("This account is inactive."))
self.check_for_test_cookie()
return self.cleaned_data

You haven't shown us what your LoginForm looks like. Assuming it just has two CharFields, I wouldn't expect any errors as long as you have provided a user name and password.
To show errors for an invalid username and password combination, your form would have to include logic to authenticate the login data.
Luckily, you don't have write this yourself, you can use Django's built in AuthenticationForm. It will return an error if the username and password are not valid.
from django.contrib.auth.forms imoirt AuthenticationForm
from django.contrib.auth import login as auth_login
# in the view
if request.method == "POST":
form = AuthenticationForm(data=request.POST)
if form.is_valid():
# if the form is valid, the user has provided a valid
# username and password. We can get the user with the
# form.get_user method and log them in
auth_login(request, form.get_user())
# return suitable ajax responses

try something like:
return HttpResponse(simplejson.dumps({'errors': form.errors.as_text()}), content_type='application/json')

Related

Any Possibility to put condition on Password Required in Django Custom Auth?

I want the registered user to log in with the Email or PhoneNumber and the Password first. If the user forgot the Password then there should be the possibility to log in with OTP bypassing the Password which would be provided via SMS on the User Phone Number. So Is there any possibility to achieve that?
Here are official docs where the password field is always required.
https://docs.djangoproject.com/en/4.0/topics/auth/customizing/#a-full-example
I know we can change the username to the email or for a phone number if we want but how do we put the condition to login with Password/Random OTP. So how we can achieve that? a suggestion would be appreciated. Thanks
You can make your own CustomLoginBackend as
from django.contrib.auth import get_user_model
class CustomLoginBackend(object):
def authenticate(self, request, email, password, otp):
User = get_user_model()
try:
user = User.objects.using(db_name).get(email=email)
except User.DoesNotExist:
return None
else:
if password is not None:
if getattr(user, 'is_active', False) and user.check_password(password):
return user
else:
if getattr(user, 'is_active', False) and user.otp == otp: #<-- otp included in user table
return user
return None
Then in your login views.
from django.contrib.auth import authenticate, login
from django.contrib import messages
def login_view(request):
if request.method == 'POST':
email = request.POST.get('email', None)
password = request.POST.get('password', None)
otp = request.POST.get('otp', None)
user = authenticate(request, email=email, password=password, otp=otp)
if user is not None:
login(request, user)
# redirect to a success page
return redirect('dashboard')
else:
if password is not None:
# return either email or password incorrect
messages.error(request, "Invalid Email or Password")
return redirect('login')
else:
# return invalid otp
messages.error(request, "Invalid OTP")
return redirect('login')
return render(request, 'login.html')
And at last don't forgot to add AUTHENTICATION_BACKENDS in your settings.py as
AUTHENTICATION_BACKENDS = ['path_to_your.CustomLoginBackend ',]
Yes we can do that using forced login here is an example how i have did this please have a look i have a profile which is one to one relation with user
def login_otp(request):
mobile = request.session['mobile']
context = {'mobile':mobile}
if request.method == 'POST':
otp = request.POST.get('otp')
profile = Profile.objects.filter(mobile=mobile).first()
if otp == profile.otp:
user = User.objects.get(id = profile.user.id)
login(request , user)
return redirect('cart')
else:
context = {'message' : 'Wrong OTP' , 'class' : 'danger','mobile':mobile }
return render(request,'login_otp.html' , context)
return render(request,'login_otp.html' , context)

Django - Why do I need to specify the user.backend when logging in with a custom backend?

The code works as is, I'm just hoping somebody can provide an explanation here.
I set up a custom backend for my app. Code below:
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth import get_user_model
class AuthenticationBackend(BaseBackend):
def authenticate(self, request, username=None, password=None, email=None):
UserModel = get_user_model()
try:
user = UserModel.objects.get(email=email)
except UserModel.DoesNotExist:
return None
else:
if user.check_password(password):
return user
return None
And here is the view:
def login_view(request):
form = LoginForm(request.POST or None)
if request.POST and form.is_valid():
user = form.login(request)
if user:
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
print(request.user)
return redirect('tasks')
context = {
'form': form
}
return render(request, 'users/login/index.html', context)
Along with the form (Note much of the login functionality was abstracted to the form)
class LoginForm(forms.Form):
email = forms.CharField(max_length=255, required=True, widget=forms.TextInput(attrs={'class': 'form_input'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form_input'}), required=True)
def clean(self):
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
user = authenticate(email=email, password=password)
if not user or not user.is_active:
raise forms.ValidationError("Sorry, that login was invalid. Please try again.")
return self.cleaned_data
def login(self, request):
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
user = authenticate(email=email, password=password)
return user
In the login_view code, I had an issue. Before adding the "user.backend = ..." line, the system would login the user successfully, however upon redirecting to the 'tasks' view, the user would go back to Anonyomous.
After specifying the backend for the user prior to login, the code works fine.
Why do I need to specify the backend for the user prior to login? Is this because I'm using a custom backend? Did I mess up on the code somewhere?
Thank you in advanced!
Actually when you create more than one backend in the Django and register that backend in the Django settings Django is not able to identify for which backend this login functionality is so for that we have to specify the backend at login time or the other way is you can delete the default Django login backend but, if you delete that after that Django admin login might not work.

Getting error 'django.contrib.auth.models.User.DoesNotExist: User matching query does not exist'

A similar question has been asked before but after going through all of them I was not able to find any answer to fit my case.
I am using Django's built-in authentication system to authenticate and log in a user. The user uses a log in form on index form and is supposed to be then redirected to a different url.
However after I log in with a username and password that are both valid entries, I am not redirected to the next url as I should be, and I get this error:
django.contrib.auth.models.User.DoesNotExist: User matching query does not exist.
These are my import lines for authenticate, login, and then for User.
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
But I don't think the problem is there.
It can't find the user but I don't know why that could be, because I am creating a username in the form and a password so it should be present.
Here is my login code:
def index(request):
if request.method == 'POST':
print("Received POST")
form = LoginForm(request.POST)
if form.is_valid():
print("FORM is Valid")
# proceed with registration
username, pwd = request.POST.get("username", None), request.POST.get("password", None)
if not username or not pwd:
print("nobody around here")
return HttpResponse("Username or password not present")
user = User.objects.get(username=username)
if user:
user = authenticate(username=username, password=pwd)
else:
user = User.objects.create_user(username, username, pwd)
login(request, user)
return redirect("dashboard")
else:
print("FORM is NOT VALID")
template = loader.get_template('index.html')
context = {
'username': 'Ralf',
'form': form,
}
return HttpResponse(template.render(context, request=request))
else:
# load the template file
template = loader.get_template('index.html')
context = {
'username': 'Ralf',
'form': LoginForm(),
}
return HttpResponse(template.render(context, request=request))
EDIT: I tried using a try except block and now the page will not load the form:
Here is the code I used:
if form.is_valid():
print("FORM is Valid")
# proceed with registration
username, pwd = request.POST.get("username", None), request.POST.get("password", None)
if not username or not pwd:
print("nobody around here")
return HttpResponse("Username or password not present")
try:
user = User.objects.get(username=username)
user = authenticate(username=username, password=pwd)
except:
user = User.objects.create_user(username, username, pwd)
login(request, user)
return redirect("dashboard")

login authentication in django

I want to use the authenticaton for custom user model in django. i just created the authentication for custom user model. but it's not validating the username and password. anyone help for that where i was mistaken the code.
Here it is my views.py file :
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
def loginpage(request):
if request.method =='POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request,username=username,password=password)
if user is not None:
login(request,user)
return redirect('profile')
else:
return render(request, 'login.html', {})
Your authenticate logic is wrong. Because you gave queryset to authenticate function.You can provide username and password directly. There is a sample for authenticate based on doc
And change your request.POST.['username'] with request.POST.get("username"),
request.POST.['password'] with request.POST.get("password")
from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
# User exist
else:
# No user founded with this username and password

login CSRF verification failed. Request aborted

I extends AbstractBaseUser and I try to write login function but i got this error:
CSRF verification failed. Request aborted.
in views.py
def admin_login(request):
username = password = ''
if request.POST:
request.session.delete_test_cookie()
username = request.POST.get('username')
password = request.POST.get('password')
admin = Administrator.objects.all.get(username__exact=username)
if admin is not None and admin.check_password(password):
login(request, admin)
request.session['admin_id'] = admin.id
return redirect('dashborad')
return render_to_response('admin/login.html',{ 'username': username})
Keep in mind whenever you are using CSRF, you need to pass an instance of RequestContext back to the view. In addition, your form needs to have {% csrf_token %} added to it.
In your view code, you can use the render shortcut which will incude the correct context for you:
from django.shortcuts import render
def admin_login(request):
# your normal code
return render(request, 'admin/login.html', {'username': username})
The CSRF section of the documentation has a checklist of what is required in order for CSRF to work correctly.
You should also use authenticate() instead of writing your own logic:
from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
Putting all that together, your code is now:
from django.shortcuts import render
from django.contrib.auth import authenticate
from django.contrib import messages
def admin_login(request):
"""Logs in an admin user, redirecting to the dashboard"""
if request.POST:
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username, password)
if user is not None:
if user.is_active:
login(request, user)
request.session['admin_id'] = user.id
return redirect('dashboard')
else:
# do something because user was not active
messages.add_message(request, messages.ERROR, 'User Inactive')
return render(request, 'admin/login.html')
else:
# password/username combination was wrong
messages.add_message(request, messages.ERROR, 'Invalid Credentials')
return render(request, 'admin/login.html')
else:
return render(request, 'admin/login.html')
I am using the built-in messages framework to display the error messages.