Python中Django如何实现扩展user模块

各位大佬,我最近是在边学边用 django,在开发注册模块的时候遇到了问题,一天都没解决。。 django 默认的注册是只保存 username 跟 email 的,我需要更多的信息,然后新建了一个 model

class User_base(models.Model):
    user = models.OneToOneField(User)
    username = models.CharField(max_length=50)
    email = models.CharField(max_length=50)
    nick_name = models.CharField(max_length=50)
    cn_name = models.CharField(max_length=50)
    en_name = models.CharField(max_length=50)
    dept_id = models.IntegerField()
    job_title_id = models.CharField(max_length=50)
    empid = models.IntegerField()
    supervisor_empid = models.IntegerField()

然后有个表单里面设置了 dept_id 等列不为空,然后就是 view.py 里面处理接受过来的数据

    userxx = User()
    userxx.username = username
    userxx.set_password(password)
    userxx.email = emailadd
    userxx.save()

但是每次到 userxx.save 的时候都会报错 (1048, "Column 'dept_id' cannot be null"),我去表里查了一下,每次 auth_user 里面都有数据插入,但是跟 user 关联的 user_base 表里面却没有任何数据,我现在真的是被搞得头都大了。。。我在调试的时候看到 dept_id 是有值的,不知道为啥存的时候都提示 null


Python中Django如何实现扩展user模块

21 回复

查了,每次 auth_user 里面都有数据插入,但是跟 user 关联的 user_base 表里面却没有任何数据,我现在真的是被搞得头都大了。。。我在调试的时候看到 dept_id 是有值的,不知道为啥存的时候都提示 null


在Django里扩展User模型,主要有三种主流方法,看你具体需求。

1. 使用Profile模型(一对一关联) 这是最常用、侵入性最小的方法。保持Django自带的auth_user表不变,新建一个Profile模型通过OneToOneField关联它。适合添加头像、电话等额外信息。

from django.contrib.auth.models import User
from django.db import models

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    phone = models.CharField(max_length=20, blank=True)
    avatar = models.ImageField(upload_to='avatars/', blank=True)

# 创建信号,在User创建时自动创建Profile
from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

使用时通过user.profile.phone访问扩展字段。

2. 继承AbstractUser(替换整个User) 如果你需要完全替换Django的User模型,比如要改用户名字段为邮箱,或者添加大量新字段,就继承AbstractUser。这需要一开始就设置好。

# models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    # 添加新字段
    phone = models.CharField(max_length=20, blank=True)
    # 可以修改原有字段,比如使email唯一且非空
    email = models.EmailField(unique=True, blank=False)

    def __str__(self):
        return self.username

# settings.py 中必须配置
AUTH_USER_MODEL = 'your_app.CustomUser'

之后所有对User的引用都要改成get_user_model()settings.AUTH_USER_MODEL

3. 继承AbstractBaseUser(完全自定义) 当Django默认的User字段(如username、first_name)你大部分都不需要,想从头设计认证核心(比如只用邮箱或手机号登录)时用这个。最灵活,但也最复杂。

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        # 完全自定义创建用户的逻辑
        pass
    def create_superuser(self, email, password=None, **extra_fields):
        # 自定义创建超级用户的逻辑
        pass

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    is_active = models.BooleanField(default=True)
    # ... 你的其他字段
    objects = CustomUserManager()
    USERNAME_FIELD = 'email' # 指定用email作为唯一标识
    REQUIRED_FIELDS = [] # 创建超级用户时需要提示的字段

    # settings.py 同样需要配置 AUTH_USER_MODEL

总结建议: 大多数情况用Profile模型或继承AbstractUser就足够了。

手抖了。。。

没看懂,你不能直接继承 AbstractUser 吗

我查到的大部分都是用 OneToOneField 做关联的,我额外存储的信息不需要做验证的,跟 profile 差不多

看看你的 User_base 是怎么 create 的? 怀疑你 create 的时候没有设置 dept_id 的值,然后 在 User_base 定义是必须的。

这些 extend profile 最好都设置成 blank=True 吧。。。

User_base create 了吗或者只是声明了没有调用 save() ?

dept_id 具体值的是什么呢?你在 create 的时候可以具体制定的

其实自己写一个不继承 User 也无所谓吧。。之前写的时候很少用到 OnetoOneField 这种(是不是我太 low 了

blank=True 加上吧,或者每次给一个默认值

酱狗一出天地灭,加入瑞思保平安。

主要是刚上手 django,想着用自带的认证会比较方便一下


有调用 save(),就是在 save 的时候报错的,我还没建 user_base 对象,因为 user 在保存的时候一直会报这个错误,我也不知道是因为什么原因,在一点点排查。我之前建 user_base 的时候,穿进去的 form 是有 dept_id 的值的

看到你说瑞思,还以为是我学校之前的睿思呢…

你新建对象之后没有修改 dept_id 的值?
在 save 之前加一行
userxx.dept_id = dept_id

dept_id = models.IntegerField(default=0)

user.save() 的时候是不会主动创建 User_base 的, 所以绝对不会报 dept_id 的问题,
所以你还是检查一下你的 User_base 是怎么 create 的。
我怀疑你是用了 signal 去 create 而不指定 dept_id 这个非 blank=True 的字段。

你不要 AT 我了 上面好几个人喊你检查 User_base 的 create, 如果实在不想检查你就直接设置 blank=True 吧。

User()是个哪个 model.肯定是 User_base.dept_id 没有赋值.

老哥,你发的这个不是文档啊。。。

瑞思 == rails

回到顶部