django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'sso.User' that has not been installed

我出现的问题是在一个main.py 互相引用了user

look my demo:

from django.db import models
#导入时间域
from django.utils import timezone
# 懒加载可翻译
from django.utils.translation import gettext_lazy as _
# 引入 AbstractUser表,高级的功能/密码自动加密/检查密码
from django.contrib.auth.models import AbstractUser
# 导入自定义重写注册用户的管理类
from sso.main import CustomUserManager


#基类
class BaseModel(models.Model):

    #创建时间
    create_time = models.DateTimeField(default=timezone.now, null=True)

    class Meta:
        abstract = True


# 重写了原来User模型的表结构,所以必须第一次migrate前就先定义好
class User(AbstractUser):
    uid = models.BigIntegerField(primary_key=True, auto_created=True, unique=True, verbose_name=_('id全局标识'))
    email = models.CharField(unique=True, max_length=100, error_messages={'unique': _('此邮箱已被注册')})
    # 额外的
    mobile = models.CharField(unique=True, max_length=20, verbose_name=_('手机号'))
    avatar = models.ImageField(
        upload_to='avatar',  #保存上传文件的目录
        verbose_name='头像',  #admin显示文字
        null=True,
        blank=True,
    )
    # 头像本地化处理
    avatar_url = models.URLField(
        null=True,
        blank=True,
        verbose_name='头像地址',
    )
    last_login_ip = models.CharField(max_length=40, blank=True, null=True)
    last_changepwd_time = models.DateTimeField(default=timezone.now, blank=True, null=True)
    original_pwd_change = models.PositiveIntegerField(default=0)

    USERNAME_FIELD = 'email'  # 身份验证字段指向email,而不是原来的username
    REQUIRED_FIELDS = ['username']  # 注册admin用户提示选项

    # 重新定义Manager对象,在创建user的时候使用
    # email 和 password,而不是使用username和password
    objects = CustomUserManager()

    class Meta:
        managed = False
        db_table = 'authuser'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.email


# 基于角色的权限管理,使用django-admin自带表,把group当作角色

接着问题来了,attention:

objects = CustomUserManager()

Yes,你必须在单独的.py中构造它,切记不能再里面引用User模型!!!

Like This Demo:

# Create your views here.
# 引用用户注册管理类
from django.contrib.auth.models import UserManager
# 雪花发号器
from sso.db.snowflake_tool import snowflakeid

__all__ = ('CustomUserManager', )


# 自定义重写注册用户的管理类
class CustomUserManager(UserManager):
    use_in_migrations = True

    print('# # # Override the registered user management class UserManager to `CustomUserManager`')

    def _create_user(self, username, email, password, **extra_fields):
        """
        Create and save a user with the given username, email, and password.
        """
        if not email:
            raise ValueError('The given email must be set')
        # 使用雪花发号器
        uid = snowflakeid()
        email = self.normalize_email(email)
        username = self.model.normalize_username(username)
        user = self.model(uid=uid, username=username, email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user


最后在admin.py,你可以写上有关它的扩展,
Like This Demo:
# Register your models here.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
# 重新导入扩展后的user表
# from sso.models import User
# from django2education.settings import AUTH_USER_MODEL as User
from django.contrib.auth import get_user_model
User = get_user_model()
# 导入默认settings.AUTH_USER_MODEL
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q, F
from sso.hashers import md5

admin.site.register(User, UserAdmin)


# 自定义用户身份认证类方法authenticate,配置到settings.py
# 支持用户名/手机/邮箱的用户认证
class CustomBackend(ModelBackend):
    print("# # # The custom user authentication class `CustomBackend`")

    @staticmethod
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(username=username) | Q(email=username) | Q(mobile=username))
            # 统一前后端密码:由于获取vue前端的输入密码是已用md5加密,获取django-admin后台的输入密码是未加密
            password = md5(password) if len(password) < 32 else password
            if user.check_password(password):
                return user
        except Exception as e:
            print(str(e))
            return None

    def get_user(self, uid):
        try:
            return User.objects.get(id=uid)
        except Exception:
            return None


posted @ 2020-06-22 18:14  justblue  阅读(3754)  评论(0编辑  收藏  举报