Django扩展AbstractUser实现客户/商家两类用户的报错及功能咨询
问题1解答:报错原因及修复方案
报错原因
你遇到的Unknown field(s) (mobileno) specified for CustomUser报错源于三处错误配置:
mobileno字段定义在Customer、Vendor两个关联子模型中,并未在你用于认证的主用户模型CustomUser中定义,但你的admin.py、forms.py都直接在CustomUser对应的配置里引用了mobileno字段,字段不存在自然报错。- 你当前的用户模型设计逻辑错误:用邮箱替代用户名登录的核心配置(
USERNAME_FIELD = 'email'、取消username字段、指定CustomUserManager管理器)应该写在继承了AbstractUser的CustomUser类中,而不是写在普通ORM模型Customer、Vendor里,这两个子模型不参与Django Auth系统的认证逻辑,写相关配置完全无效。 - 你重复定义了
email、姓名等公共字段,CustomUser、Customer、Vendor都存这些字段会造成数据冗余,完全没必要。
修复步骤
第一步:修正models.py代码
from django.contrib.auth.models import AbstractUser, BaseUserManager from django.db import models from django.utils.translation import ugettext_lazy as _ class CustomUserManager(BaseUserManager): """Define a model manager for User model with no username field.""" def _create_user(self, email, password=None, **extra_fields): """Create and save a User with the given email and password.""" if not email: raise ValueError('The given email must be set') email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_user(self, email, password=None, **extra_fields): extra_fields.setdefault('is_staff', False) extra_fields.setdefault('is_superuser', False) return self._create_user(email, password, **extra_fields) def create_superuser(self, email, password=None, **extra_fields): """Create and save a SuperUser with the given email and password.""" extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') return self._create_user(email, password, **extra_fields) class CustomUser(AbstractUser): # 取消默认的username字段 username = None # 所有用户公共字段放在主用户表 email = models.EmailField(_('email address'), unique=True) mobileno = models.IntegerField(blank=True, null=True) # 身份标记字段 is_customer = models.BooleanField('customer status', default=False) is_vendor = models.BooleanField('vendor status', default=False) # 邮箱作为登录唯一标识 USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] # 指定自定义管理器 objects = CustomUserManager() # 子模型只保留对应身份独有的字段,不要重复存公共字段 class Customer(models.Model): customeruser = models.OneToOneField(CustomUser, on_delete=models.CASCADE, primary_key=True) # 这里只加客户独有的字段,比如收货地址、会员等级之类的 class Vendor(models.Model): vendoruser = models.OneToOneField(CustomUser, on_delete=models.CASCADE, primary_key=True) # 这里只加商家独有的字段,比如店铺名称、经营资质之类的
同时别忘了在项目settings.py里加配置:AUTH_USER_MODEL = '你的应用名称.CustomUser'
第二步:admin.py和forms.py无需改动
因为现在mobileno已经是CustomUser的字段了,你原来的admin和form配置里引用的字段都存在,不会再报错。
问题2解答:Django自带Auth功能适配性
修复上述配置后,Django自带的登录、登出、密码重置等认证功能完全可以同时适配两类用户使用:
- 两类用户底层都共用同一个
CustomUser主模型,Django Auth系统只对接AUTH_USER_MODEL指定的主用户模型,不会区分身份标记,基础认证功能可以直接复用。 - 如果需要针对两类用户做权限控制、页面跳转区分,只需要在对应业务逻辑里判断
request.user.is_customer或者request.user.is_vendor的属性值即可,不需要改造原有Auth功能的核心逻辑。
内容的提问来源于stack exchange,提问作者user17408361
相关产品推荐
相关产品推荐

