Django多自定义User模型迁移报fields.E304反向访问器冲突如何解决
报错原因
你继承的PermissionsMixin内置了groups和user_permissions两个多对多关联字段,默认的反向关联名称是固定的。两个自定义用户模型同时继承这个类,就会导致反向关联名冲突,触发E304报错。
另外你有一个配置错误:Django的AUTH_USER_MODEL全局只能设置一个,不能同时配置两个独立的用户模型,多写的配置不会生效。
解决方案
方案1:保留双用户表(适合确实需要完全隔离两张用户表的场景)
在两个自定义User类中,手动覆盖PermissionsMixin自带的两个关联字段,设置不同的related_name即可解决冲突。
首先导入依赖:
from django.contrib.auth.models import Group, Permission
修改user/models.py中的User类:
class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField(max_length=255, unique=True) name = models.CharField(max_length=255) is_active = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) # 手动覆盖字段,设置普通用户的专属related_name groups = models.ManyToManyField( Group, related_name="common_user_groups", blank=True, help_text="该用户所属的用户组", ) user_permissions = models.ManyToManyField( Permission, related_name="common_user_perms", blank=True, help_text="该用户的专属权限", ) objects = UserManager() USERNAME_FIELD = 'email'
再修改seller/models.py中的User类,使用不同的related_name:
class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField(max_length=255, unique=True) name = models.CharField(max_length=255) is_active = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) # 手动覆盖字段,设置卖家用户的专属related_name,和上面的名称不能重复 groups = models.ManyToManyField( Group, related_name="seller_user_groups", blank=True, help_text="该卖家所属的用户组", ) user_permissions = models.ManyToManyField( Permission, related_name="seller_user_perms", blank=True, help_text="该卖家的专属权限", ) objects = UserManager() USERNAME_FIELD = 'email'
改完后删除之前生成的无效迁移文件,重新执行python manage.py makemigrations和python manage.py migrate即可。如果需要实现双用户表的登录认证,还需要额外自定义认证后端,匹配对应的用户表做身份校验。
方案2:改用单用户表加角色字段(更适合新手的轻量方案)
对于刚接触Django的开发者,更推荐只用一个自定义用户模型,新增角色字段区分普通用户和卖家,避免多用户表带来的各种适配问题:
# 只用一个user/models.py的User类即可 class User(AbstractBaseUser, PermissionsMixin): ROLE_CHOICES = ( ("user", "普通用户"), ("seller", "卖家"), ) email = models.EmailField(max_length=255, unique=True) name = models.CharField(max_length=255) role = models.CharField(max_length=10, choices=ROLE_CHOICES, default="user") is_active = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) objects = UserManager() USERNAME_FIELD = 'email'
后续业务逻辑直接通过user.role判断身份即可,不需要额外调整认证、权限等默认逻辑,开发成本更低。
内容的提问来源于stack exchange,提问作者GuruRandapa
相关产品推荐
相关产品推荐

