login authentication in django - 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

Related

Custom user model in django to use phone and email both for sign up

By default django uses the USERNAME_FIELD for authentication but it takes only one field. But i want my signup form to let users sign up by using phone number or by their email, like it happens in facebook . Can anybody help me how can i achieve this ?
First of all your phone_number field should be unique and you have to create a custom backend for this and register in settings and the backend checks the user by username or phone_number then check the password of the user and if credentials are correct then login user. For example,
#backends.py
from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from django.contrib.auth import get_user_model
User = get_user_model()
class UserNamePhoneAuthBackend(ModelBackend):
"""UserName or Phone Authentication Backend.
Allows user sign in with email or phone then check password is valid
or not and return user else return none
"""
def authenticate(self, request, username_or_phone=None, password=None, role=None):
try:
user = User.objects.get(
(Q(username=username_or_phone) | Q(phone_number=username_or_phone)))
except ObjectDoesNotExist:
return None
else:
if user.check_password(password):
return user
else:
return None
def get_user(self, user_id):
try:
return CustomUser.objects.get(id=user_id)
except ObjectDoesNotExist:
return None
#settings
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"path.for.UserNamePhoneAuthBackend",
)
#views.py
from django.contrib.auth import authenticate
from django.contrib.auth import login
class UserLogin(ApiView):
def post(self, request):
username_or_phone = request.data.get("username_or_phone")
password = request.data.get("password")
user = authenticate(
username_or_phone=username_or_phone,
password=password)
if user is not None:
login(user)
# return token for user
else:
return Response("Invalid Credentials")

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.

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.

Django empty error messages

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')

How to automatically login a user after registration in django

This is what I am currently using for registration:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
messages.info(request, "Thanks for registering. Please login to continue.")
return HttpResponseRedirect("/dashboard/")
else:
form = UserCreationForm()
return render_to_response("accounts/register.html", {
'form': form,
}, context_instance=RequestContext(request))
Is it possible not to require the user to login manually after creating an account, but rather simply to log them in automatically? Thanks.
edit: I had tried the login() function without success. I believe the problem is that AUTHENTICATION_BACKENDS was not set.
Using the authenticate() and login() functions:
from django.contrib.auth import authenticate, login
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
messages.info(request, "Thanks for registering. You are now logged in.")
new_user = authenticate(username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
)
login(request, new_user)
return HttpResponseRedirect("/dashboard/")
for class based views here was the code that worked for me (originally Django 1.7, updated for 2.1)
from django.contrib.auth import authenticate, login
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.views.generic import FormView
class SignUp(FormView):
template_name = 'signup.html'
form_class = UserCreateForm
success_url='/account'
def form_valid(self, form):
#save the new user first
form.save()
#get the username and password
username = self.request.POST['username']
password = self.request.POST['password1']
#authenticate user then login
user = authenticate(username=username, password=password)
login(self.request, user)
return HttpResponseRedirect(self.get_success_url)
The accepted answer doesn't seem to work with Django 4.0 (for me, at least), or alternatively it doesn't work with custom user models that have custom user managers.
This is how I solved the issue (adapted from https://stackoverflow.com/a/31491942 and https://stackoverflow.com/a/68515276):
from django.views.generic import CreateView
from django.urls import reverse_lazy
from django.contrib.auth import authenticate, login
from your.custom.user.models import User
class SignUpView(CreateView):
model = User
fields = ["username", "email", "password"]
success_url = reverse_lazy("success_url_name") # change this with your own URL
def form_valid(self, form):
# create the user object
user = form.save(commit=False)
# set password manually
# as otherwise the User will be saved with unhashed password
user.set_password(form.cleaned_data.get("password"))
# save your User object to the database
user.save()
# get email and password
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
# authenticate your user with unhashed password, because `authenticate` hashes it again
authenticated_user = authenticate(email=email, password=password)
# log in
login(self.request, authenticated_user)
return redirect(self.success_url)
You need to manually set the password, so that the database contains the hashed password. Without that, your unhashed password will be saved to the database, which will prevent you from logging in afterwards, as authentication involves hashing the password and checking that against the database.
using only "login()" in django-4.0.3
from django.contrib.auth import login
def registration(request):
if request.POST:
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}')
return redirect('home')
You can subclass Django's UserCreationForm and override it's save method to log them in when commit=True.
forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login
class CustomUserCreationForm(UserCreationForm):
"""
A ModelForm for creating a User and logging
them in after commiting a save of the form.
"""
def __init__(self, request, *args, **kwargs):
super().__init__(*args, **kwargs)
self.request = request
class Meta(UserCreationForm.Meta):
pass
def save(self, commit=True):
user = super().save(commit=commit)
if commit:
auth_user = authenticate(
username=self.cleaned_data['username'],
password=self.cleaned_data['password1']
)
login(self.request, auth_user)
return user
You just need to make sure you pass in a request object when you instantiate the form. You can do that by overriding the view's get_form_kwargs method.
views.py
def get_form_kwargs(self):
form_kwargs = super().get_form_kwargs()
form_kwargs['request'] = self.request
return form_kwargs
Or, make sure when you instantiate a form_class you do CustomUserCreationForm(data=request.POST, request=self.request).
The Django auth.login function makes it easy to log in a user, given a request and User instance.
Note: remember to add the necessary imports for the following examples.
from django.contrib.auth import login
from django.shortcuts import render, redirect
In a function-based view, the following should work.
if form.is_valid():
user = form.save()
login(request, user)
return redirect("desired-url")
For a class-based view (such as CreateView or FormView), you can override the form_valid method:
def form_valid(self, form):
"""If the form is valid, save the associated model and log the user in."""
user = form.save()
login(self.request, user)
return redirect(self.success_url)