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

Django Admin未正确使用自定义UserManager问题排查

问题描述

我创建了如下自定义用户类:

class User(AbstractUser):
    objects = UserDashManager()
    custom_field = models.CharField(max_length=84)

同时编写了继承自UserManager的自定义管理器,用于在用户创建时为该自定义字段赋值:

class UserDashManager(UserManager):

    def create_user(self, username, email, password, **extra_fields):
        extra_fields.setdefault('custom_field', 'custom field value')
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(username, email, password, **extra_fields)

我已在admin.py中完成User模型的注册:

class CustomAdmin(UserAdmin):
    model = User
    list_display = ['username', 'email', 'first_name', 'last_name','is_staff','custom_field']

# Register your models here
admin.site.register(User, CustomAdmin)

但当我通过后台地址http://127.0.0.1:8000/admin/my_app/user/add/新增用户时,用户的custom_field字段值为空。
我已完成数据库迁移操作,该字段已正常存在于数据库中;同时已在settings.py中配置AUTH_USER_MODEL = 'my_app.User'。
在Django shell中创建用户时,该字段可以正常被赋值,仅通过Admin后台创建时出现字段为空的问题。

补充说明

我曾尝试将UserManager修改为如下逻辑:

class UserDashManager(UserManager):

    def create_user(self, username, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        user = self._create_user(username, email, password, **extra_fields)
        user.custom_field = 'custom field value'
        user.save()
        return user

但问题仍然存在,补充环境信息:我使用的Django版本为3.2。


问题原因

核心问题是Django默认的Admin新增用户流程不会调用你自定义管理器中的create_user方法。
Django 3.2自带的UserCreationForm(Admin新增用户时默认使用的表单)保存逻辑是直接通过ModelForm实例化User对象、设置密码后直接调用save()入库,完全不会触发User.objects.create_user()的逻辑,所以你写在create_user里的字段赋值代码,只有手动在shell等场景显式调用create_user时才会执行,Admin创建用户时根本不会走这段逻辑,自然无法给custom_field赋值。
另外当前自定义管理器还缺少create_superuser方法的重写,后续使用manage.py createsuperuser命令创建超级用户时,同样会出现custom_field为空的问题。


解决方法

根据需求选择对应方案即可:

方案1:固定默认值直接在模型层配置(最简单)

如果custom_field的默认值是固定字符串,不需要动态计算,直接在模型字段上声明默认值即可,不管通过什么入口创建用户都会自动带上默认值,不需要额外修改Manager或Admin逻辑:

class User(AbstractUser):
    objects = UserDashManager()
    # 新增default参数配置默认值
    custom_field = models.CharField(max_length=84, default='custom field value')

改完执行python manage.py makemigrations和python manage.py migrate即可生效。

方案2:适配动态赋值场景

如果custom_field的值需要动态生成(比如根据用户名生成、关联其他数据等),按以下步骤修改:

  1. 补全自定义管理器的create_superuser方法,保证命令行创建超级用户时逻辑一致:
class UserDashManager(UserManager):

    def create_user(self, username, email, password, **extra_fields):
        extra_fields.setdefault('custom_field', 'custom field value')
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(username, email, password, **extra_fields)

    # 重写create_superuser方法
    def create_superuser(self, username, email, password, **extra_fields):
        extra_fields.setdefault('custom_field', 'custom field value')
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self._create_user(username, email, password, **extra_fields)
  1. 在自定义的CustomAdmin类中重写save_model方法,在Admin新增用户时补上字段赋值逻辑:
class CustomAdmin(UserAdmin):
    model = User
    list_display = ['username', 'email', 'first_name', 'last_name','is_staff','custom_field']

    # 可选配置:如果需要在新增用户的第一步表单就显示custom_field字段,添加如下配置
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2', 'custom_field'),
        }),
    )

    # 重写save_model,新增用户时给custom_field赋值
    def save_model(self, request, obj, form, change):
        # change为False表示是新增操作,避免编辑用户时覆盖已有值
        if not change:
            # 替换成实际需要的动态赋值逻辑
            obj.custom_field = 'custom field value'
        super().save_model(request, obj, form, change)

修改完成后重启服务,再通过Admin创建用户时,custom_field就会正常赋值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 21:27:18