user.is_authenticated

I am trying to create a login and logout page, so whenever a user is logged in, it only sees the logout option.
For login and logout I am using custom Forms and models. The problem I am facing is whenver I authenticate the user in views.py and redirect to a differnt page I cannot authenticate the user in html it is always false. I used “user.is_authenticate”. I am not sure how the value is being passed to the html. If I used the standard django login and logout template, I may be able to do it easily. Kindly help.

Code:
views.py

def login(request):
    if request.method =='POST':
        print("I am here1")
        form = LoginForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')

        user = LoginAuthBackened().authenticate(request=request, username=username, password=password)
        if user:
            messages.success(request, f'Login Successful.')
            return redirect('app-workspace')
        else:
            messages.error(request, f'Password Incorrect !')
            return redirect('app-login')
    else:
        print(form.errors)
else:
    form = LoginForm()
return render(request, 'users/login.html', {'form': form})

html:
image

models.py
--------------

from django.db import models

# Create your models here.
# One Hospital can have multiple staffs. So many to one/one to many
class HospitalDataModel(models.Model):
    hospital_name = models.CharField(max_length=50)

    def __str__(self):
        return f"Hospital Added: {self.hospital_name}"


class StaffDataModel(models.Model):

    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    dept_name = models.CharField(max_length=50)
    doctor_id = models.IntegerField()
    username = models.CharField(max_length=15, null=True)
    password = models.CharField(max_length=20, null=True)
    # Since a single hospital can have multiple staff that is why one to many
    hospital = models.ForeignKey(HospitalDataModel, on_delete=models.CASCADE)

    def __str__(self):
        return f"Doctor {self.first_name} {self.last_name}"

forms.py
from django import forms
from random import randrange as rand_num
from .models import HospitalDataModel, StaffDataModel

class UserCreationForm(forms.ModelForm):

    first_name = forms.CharField(label='First Name', max_length=100)
    last_name = forms.CharField(label='Last Name', max_length=100)
    username = forms.CharField(label='Username', max_length=100)
    dept_name = forms.CharField(label='Department', max_length=50, required=False)
    doctor_id = forms.IntegerField(initial=str(rand_num(0,100)))
    doctor_id.disabled = True
    password = forms.CharField(widget=forms.PasswordInput())
    class Meta:
        model = StaffDataModel
        fields = [ 'doctor_id', 'first_name', 'last_name', 'username', 'password']

class HospitalForm(forms.ModelForm):
    class Meta:
        model = HospitalDataModel
        fields = '__all__'

class LoginForm(forms.Form):
    username = forms.CharField(label='Username', max_length=100)
    password = forms.CharField(widget=forms.PasswordInput())

login_backend

from .models import StaffDataModel

class LoginAuthBackened():

    def authenticate(self, request, username=None, password=None):
        try:
            print(username, password)
            user = StaffDataModel.objects.get(username=username)
            if user.password == password:
                return user
            else:
                return False

        except Exception as e:
          print(e)
        return None

    def get_user(self, user_id):
        try:
            return StaffDataModel.objects.get(pk=user_id)
        except:
            return None

Have you enabled the django.contrib.auth.context_processors.auth in the TEMPLATES section of your settings.py?

Also, do you mind posting your custom backend code?

I don’t know what that is. I will check and try your suggestion. I have edited my code please have a look.
FYKI, after log in I am redirecting to a page ‘app-workspace’ belongs to different app.

Are you sure user is authetincated?

If you print(request.user.is_authenticated) before return what do you read?

Where does LoginAuthBackend() comes from? Can you post the code?


In your settings.py, you should have something like this (Not the same):

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": ["templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth", ### This is the context processor I refer to
                "..."
            ]
        },
    }
]

I checked two things:
request.user --> return Anonymous user
request.user.is_authenticated --> returns False

I don’t understand why. Because using the authentication function I checked the login information from the database and I found the entry.

This is my settings.py
image

I saw that in ‘DIRS’ field we have to provide the templates directory, now since I have multiple apps for different workflows like ‘doctors’ and ‘Patient’ and they have their own templates. so do i provide the templates path like ‘doctors/templates’ and ‘patient/templates’ ?

from django.contrib.auth import authenticate, login
# After check autentication
user = authenticate(username=username, password=password)

print(user.is_authenticated, request.user.is_authenticated)

# you must login request
if user and  user.is_active:
    login(request, user)
print(user.is_authenticated, request.user.is_authenticated)

True False
True True

APP_DIRS: True tells Django to look for templates inside every app. In DIRS you can provide a list of directories.


Ok, so you have the auth context processor enabled.
I can’t see an error in the views or any other place so I suppose it has something to do with the custom backend but not 100% sure because I never used one.

I’m having difficulties following what you’re trying to do here.

Where exactly in all this code are you detecting that the user has not successfully authenticated?

Where is the view and template for this page that is saying that it is always false?

Sorry for the trouble in understanding. I will try my best to explain.

If you look into views.py “login” function, there I am authenticating the users. class “LoginAuthBackened()” takes care of authentication.

And when a user is authenticated and logged in I render a page which has only logout option on the navigation bar. And to do that I am authenticating the user in my html template file. “HTML” code is in my description.

Will this “login(request, user)” will work if I use another database like MongoDB?

Yes, it’s the view that renders that template file we need to see.

Minor point, but important for clarity and comprehension - you are not authenticating a user in the template file. You might be checking whether or not they are authenticated, but there is no authentication being performed at that point.

No, is general:

If you have an authenticated user you want to attach to the current session - this is done with a login() function.

I’m sure you figured this out already. I just wanted to confirm that my guess was correct. When verifying the user password, is it possible that Django uses some sort of encryption on the password saved in the database and when you check the condition “user.password == password”, it always returns False, thus, the user never gets authenticated?

Correct. You need to hash the input from the user, then compare that to the “password” stored in the database. In django it’s the check_password function