Authentication with custom user model - python

I want to make login and registration for a custom user with only 5 fields: user name, name, password, linkedin id and mobile number.
I made registration successfully but I am stuck with login, I cannot authenticate my user.
Is there any way to authenticate my user, or how can I login?
Currently I am getting logged in by
user = Consultants.objects.get(Q(username= username) & Q(password= password))
But i want to make login by
user=authenticate(username=username,password=password)
Note:I don't want to use django default User Model For it.
Please help me in this.
Thanks in advance.
models.py
class Consultants(models.Model):
first_name=models.CharField(max_length=255,blank=True,null=True)
username=models.CharField(max_length=255,blank=True,null=True)
password=models.CharField(max_length=50,blank=True,null=True)
mobile_no=models.CharField(max_length=255,blank=True,null=True)
linkedin_id=models.CharField(max_length=255,blank=True,null=True)
is_active=models.BooleanField(default=False)
views.py
def register(request):
context = RequestContext(request)
registered = False
print "inside register view"
if request.method == 'POST':
consultant_form = ConsultantsForm(data=request.POST)
if consultant_form.is_valid():
consultant = consultant_form.save(commit=False)
consultant.save()
registered = True
else:
print consultant_form.errors
else:
consultant_form = ConsultantsForm()
return render_to_response(
'register.html',
{'consultant_form': consultant_form, 'registered': registered},
context_instance=RequestContext(request))
def login_user(request):
context = RequestContext(request)
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
print type(username)
try:
user = Consultants.objects.get(Q(username= username) & Q(password= password))
user = authenticate(username=username, password=password)
if user.is_active:
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
a= request.user.username
return HttpResponse("welcome......you are succesfuly log in")
else:
return HttpResponse("Your account is disabled.")
except ObjectDoesNotExist:
return HttpResponse("INvalid User")

Note:I don't want to use django default User Model For it Please help
me in this. Thanks inadvance
Is your Consultants class inheriting from the base Django user class?
The authenticate() function is used to authenticate the base user model, you may not be setting a password for the user when they are created?
Another way to go about this would instead create a Profile model with all of these extra fields with a OneToOneField to the base user model, and authenticate though the Django ORM.

I think it's better to inheriting from django embedded user class, you can follow these steps:
extend your custom user class from AbstractBaseUser and PermissionsMixin
Assign and fill this config in settings.py:
AUTH_USER_MODEL = 'YOUR_CUSTOM_CLASS_IN_FULL_QUALIFIED_NAME' e.g.: 'your_app_name.Consultants'
Voila, you can use django default user crud, also authentication

Related

Django login authentication always returns none

I am using django contrip auth for authenticate user. Signup function always working and register and login user successfully but after that I m logged out and try to login again but this time login function doesnt work.
I add this codes my settings file
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
AUTH_USER_MODEL = 'app.User'
My User model seems like that in models.py
class User(AbstractUser):
pass
My Login and Register function
def dlogin(request):
if request.method=='GET':
return render(request, "login.html")
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
# Attempt to sign user in
user = authenticate(request, username=username, password=password)
print(user)
# Check if authentication successful
if user is not None:
login(request, user)
cur_user = request.user
return render(request,'index.html',{
'success':'login successful',
'user':cur_user
})
else:
return render(request,'login.html',{
'error':'Invalid username and/or password.'
})
#csrf_exempt
def signup(request):
if request.method != "POST":
return render(request, 'signup.html')
# Get form information
username = request.POST["username"]
password = request.POST["password"]
confirmation = request.POST["confirmation"]
# Ensure password matches confirmation
if password != confirmation:
return render(request,'register.html',{
'message':'Passwords dont match'
})
# Attempt to create new user
user = User.objects.create_user(username,password)
user.save()
login(request, user)
return redirect('index')
I did some research and couldn't find any problem in my code. Does anyone can help me?
I fixed it
I change this in signup function
user = User.objects.create_user(username,password)
to this
user = User.objects.create_user(username=username,password=password)
and it works but i dont know why

Authenticate the django user using phone email and username

I am trying to achieve a login functionality like so that users can log into using their Email or Phone number or it's username as well but Django provides only email field in it's User model so that I've created an another model with One-To-One-Relation to User model and provided the phone number column but now I don't know how to achieve such functionality which I mentioned earlier.
my models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user_type = models.IntegerField(choices=USER_TYPE, default=3)
mobile = models.BigIntegerField(unique=True)
my views.py
(I know it's a mess but I can't figure out how to have such functionality)
def login(request):
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
messages.success(request, 'You are logged in successfully!')
return redirect('/dashboard')
else:
user = auth.authenticate(profile_phone=username, password=password)
if user is not None:
auth.login(request, user)
messages.success(request, 'You are logged in successfully!')
return redirect('/dashboard')
else:
user = auth.authenticate(email=username, password=password)
if user is not None:
auth.login(request, user)
messages.success(request, 'You are logged in successfully!')
return redirect('/dashboard')
else:
messages.error(request, 'Invalid username or password')
return redirect('/login')
else:
if request.user.is_authenticated:
messages.success(request, 'You are already logged in')
return redirect("/dashboard")
return render(request, "accounts/login.html")
It is not true that the Django user model only provides an email field. It also has a username field as you want. Check documentation here. If you want to add a phone number or another field, you can implement like this:
from django.contrib.auth.models import User
class MyUser(User):
user_type = models.IntegerField(choices=USER_TYPE, default=3)
mobile = models.BigIntegerField(unique=True)
and the class will include everything that the base User model has.
Also, Django provides a built-in login method that you can also use. Check this tutorial.

How can i authenticate any user for login with an extra field (other then username/ email and password) in django

I am creating a user profile using django’s authentication system (from django.contrib.auth.models import User). Before this I am trying to extend the field of user using an extra field (i.e- userprofile= ceo/developer/marketinghead) in models.py. Here is my models.py file
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class extendeduser(models.Model):
userprofile_choice=(
('ceo', 'ceo'),
('developer', 'developer'),
('marketinghead', 'marketinghead'),
)
userprofile=models.CharField(choices= userprofile_choice, max_length=255, blank=False)
user=models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self) -> str:
return self.userprofile
now I am sucessfully registering the new user. Now I have created differrent html pages based on their profile. So at the time of login I take an extra input from user which is userprofile. And based on this I have created views.py for redirecting the user at correct place. Here is my views.py file :-
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
uf = request.POST['userprofile']
user = auth.authenticate(username=username, password=password)
user_profile = extendeduser.objects.filter(user = user)
# print(user_profile[0])
# print(uf)
# print(user.get_username)
# print(user.__dict__)
#print(user.get_userprofile)
if user is not None:
if uf==user_profile[0]:
if uf=='ceo':
auth.login(request, user)
messages.success(request, "You are logged-In")
return redirect('wtoday')
elif uf=='developer':
auth.login(request, user)
messages.success(request, "You are logged-In")
return redirect('swhome')
elif uf=='marketinghead':
auth.login(request, user)
messages.success(request, "You are logged-In")
return redirect('sswhome')
else:
messages.warning(request, 'Invalid Credentials!!')
return redirect('login')
else:
messages.warning(request, 'Invalid Credentials!')
return redirect('login')
else:
messages.warning(request, 'Invalid Credentials')
return redirect('login')
return render(request, 'accounts/login.html')
Everything is fine but this "if uf==user_profile[0]:" line of code is not working. basically it is checking that the "userprofile" field of any particular user which is store in database is same as at the time of login or not. I am saying this line of code is not working because when i comment that line and then without checking user profile from the databae i just redirecting them based on the data which he fiels at the time of login then it works. But I didn't want this.
Please help me out!!
You can't compare uf and userprofile[0], because uf is a string and userprofile[0] is an extendeduser object. Maybe if uf == str(userprofile[0]): is what you want.

Django - Authenticate against existing DB

Apologies if this is simple or my terminology is off, this is my first django project. I haven't been able to find a similar solution for this online.
I have an existing application, with a postgres DB where I authenticate my users. I have wrote an application in Django to interact with some tables and display info to the user. I would like to use Django to login and track User sessions against this DB. so I can use the features like
{% if user.is_authenticated %}
but I don't want to use the migrate command so I don't want to change the existing DB. I can access the table where the account info is as I created a model for it.
I see you can use remote user logon param but I cant find any sample or guide on how to use it and am completely lost.
Right now I create a login form in the views page. Then get the username and password that is entered, but I don't know what to do next. Also would need to hash the password. Is there a libray in djano that will do that for the app.
Any pointers or online guides for this would be appreciated.
Here is the views for login
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
email = form.data['account_email']
password = form.data['account_password']
user = authenticate(username=email)
if user.check_password(password):
login(request, user)
return redirect('myapp:cust_select')
else:
# Username and password did not match
raise ValidationError('Invalid Username/Password')
return render(request, 'myapp/login.html', {'form' : form}
backends.py
from django.conf import settings
from django.contrib.auth import get_user_model
class UserAuthBackend(object):
def authenticate(self, username=None, password=None):
try:
account = get_user_model()
user = account.objects.get(account_email=username)
if user:
return user
except account.DoesNotExist:
print "account not found"
return None
def get_user(self, user_id):
try:
account = get_user_model()
return account.objects.get(pk=user_id)
except User.DoesNotExist:
return None
models.py
class Accounts(AbstractUser):
account_id = models.AutoField(primary_key=True)
account_email = models.CharField(max_length=100)
account_password = models.CharField(max_length=20)
def __str__(self):
return self.account_email
class Meta:
managed = False
db_table = 'accounts'
settings.py
AUTHENTICATION_BACKENDS = ( 'myapp.backends.UserAuthBackend', )
Its keeps exiting with the same error in the sql query.
column accounts.password does not exist
LINE 1: SELECT "accounts"."password", "accounts"."last_login", "acco...
It doesnt appear to be using my Account model. It does select it from that table but how can i get it to stop requesting accounts.password and accounts.last_login as they dont exist in y Accounts model
For reference
Note: You need to do try, catch to get this code working
def login(request):
form = LoginForm()
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
username = form.data['account_email']
password = form.data['account_password']
# First authenticate
user = authenticate(request, username=username, password=password)
if user is not None :
# Succeed, now log user in
login(request,user)
return redirect('myapp:select')
else:
# Username and password did not match
raise ValidationError('Invalid Username/Password')
return render(request, 'myapp/login.html', {'form' : form})

django user logged out after password change

I am having an issue with Django users changing passwords - I have built a few production sites in Django, just none in about a year (or in 1.8), but I don't recall having this issue before.
Summary
When a user changes their password, the user is logged out, but the password is successfully changed.
Details
I have a view that allows a user to change a password, I am using standard django forms and the auth framework, and to stress: changing the password works, it just logs the user out so that they have to login again.
I actually don't mind this terribly, I would prefer that the user be redirected to their dashboard with a message update, if i need to reauth the user in the code, then I will, just seems kind of clunky.
here is my view function:
#login_required
def user_change_password(request):
"""Allows a user to change their password"""
if request.method == "POST":
form = SubscriberPasswordForm(request.POST)
if form.is_valid():
try:
request.user.set_password(form.cleaned_data['password'])
request.user.save()
except Exception, err:
print "Error changing password: {}".format(err)
messages.add_message(request, messages.ERROR, 'The password could not be changed, please try again '
'later. This admins have been notified of this error.')
else:
#this outputs True
print request.user.is_authenticated()
messages.add_message(request, messages.INFO, 'Your password has been changed successfully')
return HttpResponseRedirect("/accounts/dashboard/")
else:
form = SubscriberPasswordForm()
return render(request, "accounts/change-password.html", {"form": form})
So the password is changed, the user gets redirected to the dashboard page, the #login_required decorator then redirects them back to the login screen.
The password form is here, though it is pretty straightforward.
class SubscriberPasswordForm(forms.Form):
password = forms.CharField(widget=forms.PasswordInput)
cpassword = forms.CharField(widget=forms.PasswordInput)
def clean_cpassword(self):
password1 = self.cleaned_data.get("password")
password2 = self.cleaned_data.get("cpassword")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
For django 1.9:
from django.contrib.auth import update_session_auth_hash
def password_change(request):
if request.method == 'POST':
form = PasswordChangeForm(user=request.user, data=request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
The following fields must be supplied in the POST request:
old_password
new_password1
new_password2
See detailed docs at update_session_auth_hash
My understanding is being logged out after password change is new in Django 1.7. So you will need to re-auth user in your code as you said.
See Release Notes:
https://docs.djangoproject.com/en/1.8/releases/1.7/#django-contrib-auth
Here is the specific note:
"The AbstractBaseUser.get_session_auth_hash() method was added and if your AUTH_USER_MODEL inherits from AbstractBaseUser, changing a user’s password now invalidates old sessions if the SessionAuthenticationMiddleware is enabled. See Session invalidation on password change for more details including upgrade considerations when enabling this new middleware."
See Documentation:
https://docs.djangoproject.com/en/1.7/topics/auth/default/#session-invalidation-on-password-change
For Django 1.8
Simply call update_session_auth_hash after set_password like so:
from django.contrib.auth import update_session_auth_hash
request.user.set_password(form.cleaned_data['password'])
update_session_auth_hash(request, request.user)
for Django 3, Django 1.8+ use this link:
https://docs.djangoproject.com/en/3.2/topics/auth/default/#django.contrib.auth.update_session_auth_hash
or use this code:
from django.contrib.auth import update_session_auth_hash
def password_change(request):
if request.method == 'POST':
form = PasswordChangeForm(user=request.user, data=request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
else:
...

Categories