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

Django注册表单提交时触发IntegrityError(非空约束失败)问题求助

Django注册表单提交时触发IntegrityError(非空约束失败)问题求助

嗨,我仔细看了你的问题和代码,这个错误的根源很清晰:你在创建用户的时候,第一次保存用户实例时phone_number字段是空的,而数据库里这个字段被设置为非空约束,所以触发了IntegrityError。下面给你拆解问题原因和具体的解决办法:

问题根源分析

你的views.py里,调用Account.objects.create_user()的时候,这个方法内部已经执行了user.save()(看你的MyAccountManager里的代码),但此时user的phone_number字段还没有被赋值——你是在create_user之后才设置user.phone_number = phone_number再save(),但这一步已经晚了,第一次save()的时候数据库就会检查phone_number的非空约束,直接抛出错误。

另外你的models.py里phone_number字段定义是models.IntegerField(),没有设置null=True或blank=True,所以数据库层面强制要求这个字段必须有值。

解决办法(推荐第一种)

方法1:修改用户管理器,让create_user直接接收并赋值phone_number

这是最规范的做法,让用户创建时就带上所有必填字段:

  1. 先修改models.py里的MyAccountManager的create_user方法:
class MyAccountManager(BaseUserManager):
    def create_user(self, first_name, last_name, username, email, phone_number, password=None):
        if not email:
            raise ValueError('user must have an email address ')
        if not username:
            raise ValueError('user must have an username ')
        # 新增手机号非空校验
        if not phone_number:
            raise ValueError('user must have a phone number ')
        
        user = self.model(
            email = self.normalize_email(email),
            username = username,
            first_name = first_name,
            last_name = last_name,
            phone_number = phone_number,  # 新增:创建实例时直接赋值手机号
        )
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    # 同步修改create_superuser方法,让它也能传递phone_number
    def create_superuser(self, first_name, last_name, email, username, phone_number, password):
        user = self.create_user(
            email= self.normalize_email(email),
            username = username,
            password = password,
            first_name = first_name,
            last_name = last_name,
            phone_number = phone_number,  # 新增传递这个参数
        )

        user.is_admin = True
        user.is_active = True
        user.is_staff = True
        user.is_superadmin = True
        user.save(using=self._db)

        return user
  1. 然后修改views.py里的调用代码,直接把phone_number传给create_user:
# 替换原来的create_user调用
user = Account.objects.create_user(
    first_name = first_name, 
    last_name = last_name, 
    email = email, 
    username = username, 
    password = password,
    phone_number = phone_number  # 新增传递这个参数
)
# 这里就不需要再写user.phone_number = phone_number和user.save()了

方法2:临时允许phone_number为空(不推荐,除非业务允许)

如果暂时不想修改管理器,也可以先修改模型字段,允许它暂时为空,之后再赋值:
修改models.py里的phone_number字段:

phone_number= models.IntegerField(null=True, blank=True)

然后运行python manage.py makemigrations和python manage.py migrate更新数据库。不过这种方法会导致数据库里可能存在phone_number为空的用户,不符合业务要求的话不建议使用。

额外的小建议

手机号用IntegerField其实不太合适:

  • 手机号可能包含前置零(比如某些地区的号码),用数字类型会丢失前置零
  • 部分地区的手机号长度可能超过数据库INT类型的限制(比如MySQL的INT最大支持10位数字,11位手机号需要用BigIntegerField)
  • 手机号是标识,不是用来做数值计算的,更适合用字符串存储

所以建议把phone_number改成CharField:

phone_number = models.CharField(max_length=20)  # 20位足够存带区号的手机号

备注:内容来源于stack exchange,提问作者Web Extol College

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 16:40:27