Django - Authenticate against existing DB - python

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

Related

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.

Checking if admin is logged in

I am trying to check if current logged in user is admin then allow them to access admin page else return to homepage.
heres my view.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth import login, logout, authenticate
from django.contrib import messages
from teacher.models import users
def login(request):
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = authenticate(username = username, password = password)
if user is not None:
login(request, user)
print (user)
messages.success(request, "You have successfully Logged In.")
return redirect('index')
else:
messages.error(request, "You have entered invalid credentials. Please try again")
return redirect('login')
else:
return render(request, 'main/login.html')
def admin(request):
user = users.objects.get(category = 'admin')
if user:
return render(request, 'main/admin.html')
elif Exception:
return render(request, 'main/home.html')
heres my models.py
class users(models.Model):
_id = models.AutoField
name = models.CharField(max_length = 100)
username = models.CharField(max_length = 100)
email = models.EmailField(max_length=254)
hpassword = models.CharField(max_length = 255)
category = models.CharField(max_length=50, default= "teacher")
I have tried using different method of query. But I end up getting error page as 'user matching query doesn't exist'. Also it doesn't check if user is logged in or not. Even if user is not logged in it returns to admin page.
did you search about decorators? have a look Check admin login on my django app
and for dashboard access check Django login Decorator you can redirect the user back to login pageif not logged in.
from django.contrib.auth.decorators import login_required
#login_required
def my_view(request):
...
for 2nd 'user matching query doesn't exist'.
check if you have a database table. make sure have run migrations
and use Try Exception
try:
user = users.objects.get(category = 'admin')
if user:
return render(request, 'main/admin.html')
except Exception as e:
return render(request, 'main/home.html')
default User class in django have a boolean field called 'is_superuser' which define is user admin or not.

Django user turns into Anonymous User

I'm trying to perform django authentication using a custom user model. Note this is for a school project and not
I have the following User model
class User(AbstractBaseUser):
userID = models.AutoField(primary_key=True)
username = models.CharField(max_length=20, unique=True)
password = models.CharField(max_length=24)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=50)
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["first_name", "last_name"]
def get_full_name(self):
return self.first_name + " " + self.last_name
def get_short_name(self):
return self.username
class Meta:
db_table = "User"
app_label = "funbids"
managed = False
I have my model defined in settings.py
AUTH_USER_MODEL = 'funbids.User'
I'm also using a custom auth backend. Note this is just a test using cleartext passwords (I'm aware this is a terrible idea to do in any production environment). I'm using a custom auth backend because a requirement for this app is to authenticate using raw SQL queries with an existing database.
class AuthBackend(object):
"""
Authenticate a user in funbids
"""
def authenticate(self, request, username=None, password=None):
# Test credentials
cursor = connections["funbids"].cursor()
cursor.execute("SELECT 1 FROM User WHERE username=%s AND password=%s", [username, password])
if cursor.fetchone():
# Have to grab the model, then authenticate
user = User.objects.get(username=username)
return user
else:
return None
def get_user(self, user_id):
try:
return User.objects.get(username=user_id)
except User.DoesNotExist:
return None
Everything seems to work in my login view.
def login_user(request, login_failed=False):
# Redirect the user to the index if they're already authenticated and arrive at the login page
if request.user.is_authenticated:
return redirect("funbids:index")
# Get the username and password from POST data
username = request.POST.get("username", "")
password = request.POST.get("password", "")
next = request.POST.get("next", "")
# Attempt to authenticate the user if both a username and password are present
if username and password:
log.debug("User %s requesting login" % username)
# Test credentials
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
log.debug("authenticated user is: %s" % request.user)
request.session.set_expiry(46800)
else:
login_failed = True
if request.user.is_authenticated:
# Authentication succeeded. Send the user to the original page they requested
# using the the "next" POST data or the index.
log.debug("Successfully authenticated user %s" % request.user)
if next:
return redirect(next)
else:
return redirect("funbids:index")
else:
# Failed authenticate, send back to login page
log.debug("Failed to authenticate user %s" % username)
# No credentials present/user failed auth - just load the page and populate the "next" form input
# in case the user was redirected here from a view they couldn't access unauthenticated.
next = request.GET.get("next", "")
try:
template = loader.get_template("funbids/login.html")
except TemplateDoesNotExist:
raise Http404("Page Not Found")
context = {
"pagetitle": "Welcome to FunBids!",
"next": next,
"login_failed": login_failed,
"template": template,
"request": request,
}
# Return the rendered page for display.
return render(request, template_name="funbids/page.html", context=context)
The debug statement prints our the username perfectly, something like:
[DEBUG] Successfully authenticated user adam
HOWEVER
Once I switch to another view, I'm no longer logged in. Instead, I'm an anonymous user, for instance:
def search(request):
log.debug("request user is: %s" % request.user)
try:
template = loader.get_template("funbids/search.html")
except TemplateDoesNotExist:
raise Http404("Page Not Found")
context = {
"pagetitle": "Search items for sale",
"template": template,
"request": request,
}
# Return the rendered page for display.
return render(request, template_name="funbids/page.html", context=context)
This time the debug statement prints out:
[DEBUG] request user is: AnonymousUser
I've done some reading on the issue and found that this happens when a user authenticates, but doesn't login. However, I can login successfully without any issues, so I'm not sure what's going on.
Would appreciate any help...thanks.
It turns out the problem was very subtle. Django wasn't able to get my user because my get_user method was wrong in my auth backend.
return User.objects.get(username=user_id)
should be
return User.objects.get(userID=user_id)
as the "userID" field is the primary key.

Django 2.0 User_Auth -> best practice to check if Username and Email exists

At my Django project Email and Username must be unique.
I want to check if they exists, but Django User model don't provide me the method like
.filter(), .count() or .exists() unfortunately. ( I don't know why.)
django.contrib.auth - User
def signup(request):
if request.method == 'POST':
username= request.POST['username']
email = request.POST['email']
password = request.POST['password']
user = User.objects.create_user(username=username, email=email, password=password)
user.save()
return HttpResponse(status=200)
else:
"""Return template with sign up page."""
return render(request, "account/account_signup.html")
I want to check in this below way, because I need separate the HTTP Response Code.
if User.objects.filter(username=username).count() > 0:
return HttpResponse(status=401)
if User.objects.filter(email=email).count() > 0:
return HttpResponse(status=402)
I know, that Django raise me the error when I try create existing username:
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: auth_user.username
But I want to check it in views layer.
Thanks in advance!
Django User model manager has the same methods as other models. So you can check for existing username or email using this for example (similar to your code, but using .exists(), to avoid count operation).
if User.objects.filter(email=email).exists():
return HttpResponse(status=401)

Authentication with custom user model

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

Categories