Search code examples
djangocustomizationdjango-authenticationdjango-auth-models

When using custom AuthBackend, unable to use request.user.is_authenticated or @login_required decorator


Firstly I'm coming from a PHP background and new to Django. And I'm trying to upgrade a webapp from a PHP framework to Django, keeping the database unchanged.

The built-in authentication in Django is bit confusing, as my User table is different to what is expected in django's auth.User modal.

In my usecase, I have an Employee entity whose login account is created at the instance of creating the Employee itself.

The authentication part I managed to complete by implementing a custom AuthBackend.

But now, I'm unable to use the @login_required decorator for other views post-login, because it throws and error 'User' object has no attribute 'is_authenticated'.

In order to use is_authenticate method my User modal must then extend from auth.AbstractUser or auth.AbstractBaseUser.

How can I keep the original table structure for User modal, but still get around these authentication functions in django?

---- Update to question ---- This is my user modal.

class User(models.Model):
    employee = models.ForeignKey(Employee, models.DO_NOTHING)
    user_role = models.ForeignKey(UserRole, models.DO_NOTHING, blank=True, null=True)
    username = models.CharField(max_length=50, blank=False, null=False)
    password = models.CharField(max_length=50, blank=True, null=True)
    created_on = models.DateTimeField()
    last_updated_on = models.DateTimeField(blank=True, null=True)
    last_password_change = models.DateTimeField(blank=True, null=True)
    status = models.IntegerField(db_comment='0-Deleted, 1-Active, 2-New')
    last_login  = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user'

Solution

  • A simple way to fix this is just set is_authenticated to True at your custom user model, like:

    class User(models.Model):
        is_authenticated = True
        employee = models.ForeignKey(Employee, models.DO_NOTHING)
        # …

    That being said, working from the AbstractBaseUser often will automate a lot of the settings. You can still override most functionalities anyway.