Reputation: 455
I have created a custom user class which appears to be working correctly however whenever I try to log in to the admin, I keep getting the following error on the login page:
Please enter the correct username and password for a staff account. Note that both fields may be case-sensitive.
I have already created several superuser which are all saving to the DB correctly with the is_staff/is_superuser/is_active flags set to True as you can see below:
CustomUser.objects.all().values()
<QuerySet [{'id': 1, 'password': 'test', 'last_login': None, 'is_superuser': True, 'username': 'test1', 'first_name': '', 'last_name': '', 'email': '[email protected]', 'is_staff': True, 'is_active': True, 'date_joined': datetime.datetime(2020, 6, 1, 0, 17, 30, 297149, tzinfo=<UTC>), 'role_id': 1, 'user_type_id': 1, 'created_by_id': None, 'update_date': datetime.datetime(2020, 6, 1, 0, 17, 30, 298524, tzinfo=<UTC>), 'updated_by_id': None}]>
I am officially puzzled as to what I have done incorrectly... Please help me figure this one out...
models.py:
from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.conf import settings
class UserType(models.Model):
"""
This model defines the types of users which are allowed to be created in the application. Examples include:
API Read Only User
API Full CRUD User
Business User
"""
name = models.CharField(max_length=50, blank=False, null=False)
description = models.TextField()
active = models.BooleanField(default=True)
creation_date = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, null=True, blank=True,
related_name='user_type_created_by')
update_date = models.DateTimeField(auto_now=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, null=True, blank=True,
related_name='user_type_updated_by')
class Role(models.Model):
"""
This model defines the job code/organization role a particular user is related to within their organization.
Examples include:
System User
Business User
Business User Manager
"""
name = models.CharField(max_length=50)
description = models.TextField()
active = models.BooleanField(default=True)
creation_date = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, null=True, blank=True,
related_name='role_created_by')
update_date = models.DateTimeField(auto_now=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, null=True, blank=True,
related_name='role_updated_by')
class CustomBaseUserManager(BaseUserManager):
"""
Defined a custom base user manager class so as operations are executed against the CustomUser model, application
specific fields can be utilized.
"""
def create_user(self, role, user_type, username=None, email=None, password=None):
# Verify that email was submitted
if not email:
raise ValueError('Email is required to create a user')
else:
email = BaseUserManager.normalize_email(email)
# If no username was submitted but email was, assign email to the username
if not username:
username = email
# Validate and get role ID from Role model
role = Role.objects.get(id=role, active=True)
# Validate and get the user_type ID from UserType model
user_type = UserType.objects.get(id=user_type, active=True)
user = self.model(
email=email,
username=username,
role=role,
user_type=user_type
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, role, user_type, username=None, email=None, password=None):
# Verify that email was submitted
if not email:
raise ValueError('Email is required to create a user')
else:
email = BaseUserManager.normalize_email(email)
# If no username was submitted but email was, assign email to the username
if not username:
username = email
# Validate and get role ID from Role model
role = Role.objects.get(id=role, active=True).id
# Validate and get the user_type ID from UserType model
user_type = UserType.objects.get(id=user_type, active=True).id
user = self.create_user(
email=email,
username=username,
role=role,
user_type=user_type
)
user.is_staff = True
user.is_superuser = True
user.is_active = True
user.is_admin = True
user.set_password(password)
user.save(using=self._db)
return user
class CustomUser(AbstractUser):
"""
This is a custom user model allowing for the required relationship between a user and a specific role as defined
by the organization. The only roles which will be allowed to be assigned to users are those which are active at the
time the user is being created.
"""
role = models.ForeignKey(Role, on_delete=models.DO_NOTHING, limit_choices_to={'active': True}, null=False,
blank=False)
user_type = models.ForeignKey(UserType, on_delete=models.DO_NOTHING, limit_choices_to={'active': True}, null=False,
blank=False)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, null=True, blank=True,
related_name='user_created_by')
update_date = models.DateTimeField(auto_now=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, null=True, blank=True,
related_name='user_updated_by')
objects = CustomBaseUserManager()
REQUIRED_FIELDS = AbstractUser.REQUIRED_FIELDS + [
'role',
'user_type'
]
def get_full_name(self):
"""
Return the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def __str__(self):
return '{} <{}>'.format(self.get_full_name(), self.email)
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
settings.py:
"""
Django settings for CategoryManager project.
Generated by 'django-admin startproject' using Django 3.0.6.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
SESSION_COOKIE_DOMAIN = '127.0.0.1:8000/'
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'l%sn*03#ls^d6e5e-&)u93lyqzvh$bh1nij)ye2h4la$&jz^t!'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'Users',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'CategoryManager.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'CategoryManager.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Custom user definition
AUTH_USER_MODEL = 'Users.CustomUser'
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
AUTHENTICATION_BACKENDS = (
# Needed to login by custom User model, regardless of `allauth`
"django.contrib.auth.backends.ModelBackend",
)
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
SOLVED: Turns out there was some issue in my local cache which was preventing django from being able to actually allow me to log in. Once I cleared my cache locally, I was able to log in.
Upvotes: 1
Views: 791
Reputation: 455
SOLVED: Turns out there was some issue in my local cache which was preventing django from being able to actually allow me to log in. Once I cleared my cache locally, I was able to log in.
Upvotes: 0
Reputation: 673
under create_superuser method change user=self.model to user=self.create_user
Upvotes: 0