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

如何在Django中正确配置自定义UserCreationForm?

解决自定义UserCreationForm的FieldError问题

报错原因很直接:默认的UserCreationForm自带username字段,但你的MyUser模型没有这个字段(你用email作为USERNAME_FIELD),继承后自然会找不到该字段报错。下面是完整的修正步骤和代码:

第一步:修正MyUser模型与管理器的隐性问题

你的模型和管理器里还有几个不符合Django规范的点,先一起修复:

模型修正点:

  1. 把required_fields改为REQUIRED_FIELDS:Django只识别大写的这个常量,用来标记创建用户时除USERNAME_FIELD外的必填字段。
  2. 删除自定义的password字段:AbstractBaseUser已经内置了密码相关的字段与加密逻辑,手动添加会导致冲突。
  3. 调整REQUIRED_FIELDS内容:移除password,因为密码是通过set_password方法处理的,不需要放在这里。

管理器修正点:

create_staffuser和create_superuser方法调用create_user时参数错误,且缺少必填的fname、lname、phone参数,需调整方法定义与调用逻辑。

修正后的models.py:

from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import PermissionsMixin
import uuid

class UserManager(BaseUserManager):
    def create_user(self, fname, lname, email, phone, password=None):
        if not email:
            raise ValueError('必须输入邮箱地址')

        user = self.model(
            fname=fname,
            lname=lname,
            email=self.normalize_email(email),
            phone=phone,
            is_superuser=False
        )

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

    # 调整方法参数,接收必填字段
    def create_staffuser(self, fname, lname, email, phone, password):
        user = self.create_user(fname, lname, email, phone, password)
        user.staff = True
        user.save(using=self._db)
        return user

    # 同样调整参数,确保传入必填字段
    def create_superuser(self, fname, lname, email, phone, password):
        user = self.create_user(fname, lname, email, phone, password)
        user.staff = True
        user.admin = True
        user.is_superuser = True
        user.save(using=self._db)
        return user

class MyUser(AbstractBaseUser, PermissionsMixin):
    fname = models.CharField(max_length=100)
    lname = models.CharField(max_length=100)
    email = models.EmailField(max_length=200, unique=True)
    phone = models.CharField(max_length=15)
    user_id = models.UUIDField(editable=False, primary_key=True, default=uuid.uuid4)
    is_active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False)
    admin = models.BooleanField(default=False)    

    USERNAME_FIELD = 'email'
    # 修正为大写常量,移除password
    REQUIRED_FIELDS = ['fname', 'lname', 'phone']

    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin

    objects = UserManager()

第二步:修正MyUserSignup表单

核心是不要继承UserCreationForm.Meta的默认字段(它包含username),手动指定表单需要的字段:email(作为用户名)、password1、password2(UserCreationForm自带的密码输入与确认字段),再加上自定义的fname、lname、phone。

同时修正clean_email方法的错误,add_error需要明确指定对应的字段名。

修正后的forms.py:

from django import forms
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth import get_user_model

MyUser = get_user_model()

class MyUserLogin(AuthenticationForm):
    class Meta:
        model = MyUser
        fields = ['email', 'password']
        
class MyUserSignup(UserCreationForm):
    class Meta:
        model = MyUser
        # 手动指定字段,去掉默认的username,替换为email和密码字段
        fields = ['email', 'fname', 'lname', 'phone', 'password1', 'password2']

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if MyUser.objects.filter(email__iexact=email).exists():
            # 指定错误对应的字段为email
            self.add_error('email', '该邮箱已注册账号')
        return email

验证效果

修改完成后,表单会正确渲染所有自定义字段,不会再出现username字段不存在的错误,同时模型与管理器的逻辑也完全符合Django自定义用户模型的规范,避免后续出现隐性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:49:12