我正在使用 Python(3.7) 和 Django(2.2) 开发一个项目,其中我必须实现多种类型的用户:
- 个人帐户 - 18 岁以下
- 个人帐户 - 18 岁以上
- 家长帐户
- 教练帐户
- 管理员
除此之外,我还需要使用电子邮件
作为登录/身份验证的用户名
字段。
我尝试使用的策略是构建一个自定义基本模型作为从AbstractBaseUser
继承的User
,并创建了一个自定义用户管理器
> 将电子邮件
设为用户名
,但它不起作用。
这是我的完整模型代码:
class UserManager(BaseUserManager):
def _create_user(self, email, password, is_staff, is_superuser, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
now = timezone.now()
email = self.normalize_email(email)
user = self.model(
email=email,
is_staff=is_staff,
is_active=True,
is_superuser=is_superuser,
last_login=now,
date_joined=now,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email=None, password=None, **extra_fields):
return self._create_user(email, password, False, False, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
user = self._create_user(email, password, True, True, **extra_fields)
user.save(using=self._db)
return user
def generate_cid():
customer_number = "".join([random.choice(string.digits) for i in range(10)])
return customer_number
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
is_personal_above_18 = models.BooleanField(default=False)
is_personal_below_18 = models.BooleanField(default=False)
is_parent = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % self.pk
def get_email(self):
return self.email
class PersonalAccountAbove18(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
primary_key=True, related_name='profile')
customer_id = models.BigIntegerField(default=generate_cid)
class PersonalAccountBelow18(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
primary_key=True, related_name='profile')
customer_id = models.BigIntegerField(blank=False)
class ParentAccount(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
primary_key=True, related_name='profile')
customer_id = models.BigIntegerField(default=generate_cid)
我对我的方法感到困惑,甚至当我运行 makemigrations
时它也会返回错误:
users.User.user_permissions: (fields.E304) Reverse accessor for 'User.user_permissions' clashes with reverse accessor for 'User.user_permissions'. HINT: Add or change a related_name argument to the definition for 'User.user_permissions' or 'User.user_permissions'.
Update: I removed the
PermissionMixin
andrelated_name
attributes from child models and migrations are running now but it still require theusername
instead of
最佳答案
makemigrations
中的错误以及后来的错误(在删除 PermissionsMixin
后),需要 username
而不是 email
进行身份验证提示您尚未将自定义模型设置为 Django auth
应用程序使用的默认用户模型。因此,Django 使用 auth.User 模型作为默认用户模型,并且您的模型会像任何其他模型一样添加到项目中。因此,这两种用户模型同时存在,auth.User
是用于身份验证目的的默认/事件模型。
本质上,编辑您的 settings.py
以添加以下内容:
AUTH_USER_MODEL = '<your_app>.User'
现在 Django 将使用您自定义的 User
模型,而不是来自 auth
应用程序的模型(默认),并且 auth.User
模型将被丢弃。 auth
应用使用 get_user_model
(django.contrib.auth.get_user_model
) 函数获取项目当前事件的用户模型,该模型检查settings.AUTH_USER_MODEL
,默认情况下,系统的其余部分(例如admin
应用程序)也会检查此设置以获取当前的用户模型。因此,只要您使用 auth
应用程序,上述内容就足够了。
关于Python - 在 Django 2 中创建多种用户类型和电子邮件作为用户名字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59069679/