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

Django自定义用户应用创建超级用户时触发TypeError错误

问题分析:Django自定义用户创建超级用户时密码类型错误

问题描述

我正在为Web应用开发Django自定义用户应用,执行python manage.py createsuperuser命令创建超级用户,输入用户名、邮箱和手机号后,无论输入包含字母数字的密码还是纯字符串密码,都会触发如下错误:

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/john/venv/lib/python3.6/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "/home/john/venv/lib/python3.6/site-packages/django/core/management/__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/john/venv/lib/python3.6/site-packages/django/core/management/base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/john/venv/lib/python3.6/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 79, in execute
    return super().execute(*args, **options)
  File "/home/john/venv/lib/python3.6/site-packages/django/core/management/base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "/home/john/venv/lib/python3.6/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 189, in handle
    self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
  File "/home/john/users/models.py", line 47, in create_superuser
    return self._create_user(username, phone_number, email, password, True, True, **extra_fields)
  File "/home/john/users/models.py", line 29, in _create_user
    user.set_password(password)
  File "/home/john/venv/lib/python3.6/site-packages/django/contrib/auth/base_user.py", line 99, in set_password
    self.password = make_password(raw_password)
  File "/home/john/venv/lib/python3.6/site-packages/django/contrib/auth/hashers.py", line 79, in make_password
    % type(password).__qualname__
TypeError: Password must be a string or bytes, got int.

以下是用户模型的models.py代码:

import random

from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core import validators
from django.utils import timezone
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager, send_mail


class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, username, phone_number, email, password, is_staff, is_superuser, **extra_fields):

        now = timezone.now()
        if not username:
            raise ValueError('The given username must be set')
        email = self.normalize_email(email)
        user = self.model(phone_number=phone_number,
                          username=Username, email=email,
                          is_staff=is_staff, is_active=True,
                          is_superuser=is_superuser,
                          date_joined=now, **extra_fields)

        if not extra_fields.get('no_password'):
            user.set_password(password)

        user.save(using=self._db)
        return user

    def create_user(self, username=None, phone_number=None, email=None, password=None, **extra_fields):
        if username is None:
            if email:
                username = email.split('@', 1)[0]
            if phone_number:
                username = random.choice('abcdefghijklmnopqrstuvwxyz') + str(phone_number)[-7:]
            while User.objects.filter(username=username).exists():
                username += str(random.randint(10, 99))

        return self._create_user(username, phone_number, email, password, False, False, **extra_fields)


    def create_superuser(self, username, phone_number, email, password, **extra_fields):
        return self._create_user(username, phone_number, email, password, True, True, **extra_fields)


    def get_by_phone_number(self, phone_number):
        return self.get(**{'phone_number': phone_number})



class User(AbstractBaseUser, PermissionsMixin):

    username = models.CharField(_('username'), max_length=32, unique=True,
                                help_text=
                                    'Required. 30 characters or fewer starting with a letter. Letters, digits',
                                validators=[
                                    validators.RegexValidator(r'^[a-zA-Z][a-zA-Z0-9_\.]+$',
                                                              _('Enter a valid username starting with a-z.'
                                                                'This value may contain only letters and numbers'
                                                                'and underscore characters.'), 'invalid')
                                ],
                                error_messages={
                                    'unique':_('A user with that username already exists.'),
                                }
                                )
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), unique=True, null=True, blank=True)
    phone_number = models.BigIntegerField(_('phone number'), unique=True, null=True, blank=True,
                                          validators=[
                                              validators.RegexValidator(r'^319[0-3,9]\d{8}$',
                                                                        ('Enter a valid mobile number.'), 'egrwfk')

                                          ],
                                          error_messages={
                                              'unique': _('A user with this mobile phone number already exits')
                                          }
                                          )
    is_staff = models.BooleanField(_('staff status'), default=False,
                                   help_text='designates whether this user can log into this admin site.')

    is_active = models.BooleanField(_('active'), default=True,
                                    help_text=_('designates whether this user should be treated as active'))

    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
    last_seen = models.DateTimeField(_('last seen date'), null=True)

    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELS = ['email', 'phone_number']

    class Meta:
        db_table = 'users'
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def get_full_name(self):

        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):

        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):

        send_mail(subject, message, from_email, [self.email], **kwargs)



    @property
    def is_loggedin_user(self):

        return self.phone_number is not None or self.email is not None


    def save(self, *args, **kwargs):
        if self.email is not None and self.email.strip() == '':
            self.email = None
        super().save(*args, **kwargs)




class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nick_name = models.CharField(_('nick_name'), max_length=150, blank=True)
    avatar = models.ImageField(_('avatar'), blank=True)
    birthday = models.DateField(_('birthday'), null=True, blank=True)
    gender = models.NullBooleanField(_('gender'), help_text='femal is False, male is True, null is unset')
    province = models.ForeignKey(verbose_name=_('province'), to='Province', null=True, on_delete=models.SET_NULL)
    class Meta:
        db_table = 'user_profiles'
        verbose_name = _('profile')
        verbose_name_plural = _('profiles')


    @property
    def get_first_name(self):
        return self.user.first_name


    @property
    def get_last_name(self):
        return self.user.last_name


    def get_nick_name(self):
        return self.nick_name if self.nick_name else self.user.username


class  Device(models.Model):
    WEB = 1
    IOS = 2
    ANDROID = 3
    DEVICE_TYPE_CHOICES = (
        (WEB, 'web'),
        (IOS, 'ios'),
        (ANDROID, 'android')
    )

    user = models.ForeignKey(User, related_name='devices', on_delete=models.CASCADE)
    device_uuid = models.UUIDField(_('Device UUID'), null=True)
    last_login = models.DateTimeField(choices=DEVICE_TYPE_CHOICES, default=ANDROID)
    device_type = models.PositiveSmallIntegerField(choices=DEVICE_TYPE_CHOICES, default=ANDROID)
    device_os = models.CharField(_('device os'), max_length=20, blank=True)
    device_model = models.CharField(_('device model'), max_length=50, blank=True)
    app_version = models.CharField(_('app version'), max_length=20, blank=True)
    created_time = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'user_devices'
        verbose_name = _('device')
        verbose_name_plural = _('devices')
        unique_together = ('user', 'device_uuid',)


class Province(models.Model):
    name = models.CharField(max_length=50)
    is_valid = models.BooleanField(default=True)
    modified_at = models.DateTimeField(auto_now=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

问题原因及修复

核心问题

错误提示Password must be a string or bytes, got int的本质是参数传递顺序完全混乱,根源有两个笔误:

  1. 必填字段属性拼写错误
    在User类中,你把REQUIRED_FIELDS写成了REQUIRED_FIELS(少了末尾的字母D)。Django的createsuperuser命令依赖这个属性识别必填字段,拼写错误导致命令无法正确解析输入的参数顺序,把整数类型的phone_number传到了password参数的位置,最终触发类型错误。

  2. _create_user方法内的变量名错误
    在_create_user创建用户实例时,你写了username=Username,这里的Username是大写的,属于未定义的变量,后续会引发NameError(当前错误栈未触发是因为参数错误先出现了)。

修复步骤

  1. 修正必填字段属性拼写:
# 原错误代码
REQUIRED_FIELS = ['email', 'phone_number']
# 修改为
REQUIRED_FIELDS = ['email', 'phone_number']
  1. 修正_create_user内的变量名:
# 原错误代码
user = self.model(phone_number=phone_number,
                  username=Username, email=email,
                  ...)
# 修改为
user = self.model(phone_number=phone_number,
                  username=username, email=email,
                  ...)

完成以上修改后,重新执行python manage.py createsuperuser即可正常创建超级用户。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:50:22