You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Django User模型后无法登录Admin面板的问题排查与解决

自定义Django User模型后超级用户无法登录Admin面板的问题排查

我自定义了Django的User模型,但创建的超级用户无法登录Admin面板,以下是我的代码和环境信息,求排查原因及解决方法:

环境信息

  • Django 3.2
  • Python 3.9
  • PostgreSQL
  • Docker(开发环境)

相关代码

users/models.py(原文件名为users/user.py,修正命名规范)

from django.contrib.auth.models import AbstractUser
from django.db import models
from ..managers.user import UserManager

class User(AbstractUser):
    objects = UserManager()

managers/user.py

from django.contrib.auth.models import BaseUserManager

class UserManager(BaseUserManager):
    def create_superuser(self, username, email=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self.create_user(username, email, password, **extra_fields)

    def create_user(self, email, username=None, password=None, **extra_fields):
        if not username:
            raise ValueError('The username field must set')
        email = self.normalize_email(email)
        user = self.model(username=username, email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self.db)
        return user

users/serializers.py(原文件名为user/serializer.py,修正拼写)

from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from rest_framework import serializers

User = get_user_model()

class UserReadSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username')

class UserWriteSerializer(serializers.ModelSerializer):
    password = serializers.CharField(validators=[validate_password], write_only=True)
    class Meta:
        model = User
        fields = ('password', 'username')

    def create(self, validated_data):
        password = validated_data.pop('password')
        username = validated_data.get('username')
        user = User.objects.create_user(username=username, password=password)
        return user

settings/base.py

from typing import List

DEBUG = True  # 生产环境需设为False
SECRET_KEY = NotImplemented

ALLOWED_HOSTS: List[str] = ['*']
CORS_ALLOW_ALL_ORIGINS = True
CSRF_TRUSTED_ORIGINS: List[str] = []

INTERNAL_IPS = [
    '127.0.0.1',
]

APPEND_SLASH = False

# 应用定义
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # 第三方应用
    'corsheaders',
    'rest_framework',
    'rest_framework_simplejwt',
    'django_filters',
    'storages',

    # 自定义应用
    'cores.authentication.apps.AuthenticationConfig',
    'cores.users.apps.UsersConfig',
    'cores.cards.apps.CardsConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'cores.project.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',
            ],
        },
    },
]

ASGI_APPLICATION = 'cores.project.asgi.application'
WSGI_APPLICATION = 'cores.project.wsgi.application'

# 数据库配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'trinion',
        'USER': 'trinion',
        'PASSWORD': 'trinion',
        'HOST': 'localhost',
        'PORT': '5432',
        'ATOMIC_REQUESTS': True,
        'CONN_MAX_AGE': 600,
    }
}

# 密码验证器
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',
    },
]

AUTH_USER_MODEL = 'users.User'

LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True

# 媒体文件配置
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

# 静态文件配置
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'

DATA_UPLOAD_MAX_MEMORY_SIZE = 10485760  # 10MB
FILE_UPLOAD_MAX_MEMORY_SIZE = 10485760  # 10MB

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

settings/rest_framework.py

from datetime import timedelta

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(days=365),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
    'UPDATE_LAST_LOGIN': True,
}

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication',),
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.OrderingFilter',
    ],
    'DEFAULT_PARSER_CLASSES': ('rest_framework.parsers.JSONParser',),
    'TEST_REQUEST_DEFAULT_FORMAT': 'json',
}

问题排查与解决方法

1. 核心问题:UserManager方法参数顺序不匹配

你的create_superuser调用create_user时,传参顺序和create_user的定义完全颠倒:

  • create_superuser传参顺序是username, email, password
  • 但create_user的参数定义是email, username=None, password=None

这会导致:

  • 你创建超级用户时输入的username被存到了email字段
  • username字段要么是None(创建时没填邮箱),要么是你输入的邮箱地址

解决方法:修改create_user的参数顺序,匹配调用逻辑:

def create_user(self, username, email=None, password=None, **extra_fields):
    if not username:
        raise ValueError('The username field must set')
    
    # 仅当email不为空时做归一化处理
    if email:
        email = self.normalize_email(email)
    
    # 显式设置is_active,避免意外被覆盖
    extra_fields.setdefault('is_active', True)
    
    user = self.model(username=username, email=email, **extra_fields)
    user.set_password(password)
    user.save(using=self.db)
    return user

2. 修复后重新创建超级用户

先删除已创建的错误超级用户:

python manage.py shell
from django.contrib.auth import get_user_model
User = get_user_model()
User.objects.filter(is_superuser=True).delete()
exit()

然后重新创建超级用户:

python manage.py createsuperuser

3. 其他可能的问题排查

  • Admin注册问题:确保在users/admin.py中正确注册自定义User模型:
    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin
    from .models import User
    
    admin.site.register(User, UserAdmin)
    
  • CSRF验证问题:Docker环境下,添加访问地址到CSRF_TRUSTED_ORIGINS:
    # settings/base.py
    CSRF_TRUSTED_ORIGINS = ['http://localhost:8000'] # 替换成你的实际访问地址
    

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 05:35:57