我创建了一个自定义用户类,该类似乎正常工作,但是每当我尝试登录到管理员时,都会在登录页面上不断出现以下错误:
请输入员工帐户的正确用户名和密码。请注意,两个字段都可能区分大小写。
我已经创建了几个超级用户,这些超级用户都已将is_staff / is_superuser / is_active标志设置为True正确地保存到了DB,如下所示:
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}]>
我对我做错的事感到正式困惑,请帮助我弄清楚这件事...
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/'
在create_superuser方法下,将user = self.model更改为user = self.create_user