Django-使用个人资料扩展用户模型,但也可以使用不同的用户类型

时间:2019-03-24 12:42:12

标签: python django django-models django-users

我想在Django(2.2)中扩展用户模型,并将其与也具有特定字段的Host和Guest实体组合。

official documentation中,建议使用引用用户主键的OneToOne字段创建“个人资料”类。

我可以看到3种方法:

解决方案1:个人资料,主机和访客模型:

class Profile(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)

class Host(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    host_field= models.CharField(max_length=500)

class Guest(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    guest_field = models.BooleanField(null=False)

解决方案2:主机和访客模型(重复的配置文件字段)

class Host(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)
    host_field = models.CharField(max_length=500)

class Guest(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)
    guest_field = models.BooleanField(null=False)

解决方案3:配置文件模型(包含来宾和主机字段)

class Profile(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)
    is_host = models.BooleanField(null=False)       
    guest_field = models.BooleanField(null=False) 
    host_field = models.CharField(max_length=500) 

所有这些解决方案都在起作用。

我的问题是:“哪一种是最聪明的,所有事情都考虑在内”(较少的数据库访问,较少的代码编写,易于维护,较少的限制等。)

2 个答案:

答案 0 :(得分:0)

我会提出一种4:th方法,将mixin与抽象模型结合使用。这会将抽象模型的字段派生到您将其应用到的领域。这样,您无需重写代码,仍然可以将其应用于其他模型:

class ProfileMixin(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)

    class Meta:
        abstract = True

class Host(ProfileMixin):
    host_field = models.CharField(max_length=500)

class Guest(ProfileMixin):
    guest_field = models.BooleanField(null=False)

答案 1 :(得分:0)

在深入研究Django的文档并阅读了article mentioned by @sam(解释如何在Django中实现多用户类型)后,我找到了答案。

Django doc中写道:“强烈建议您设置自定义用户模型,即使默认用户模型足以满足您的需要。”

这就是我的情况:

class User(AbstractUser):
    is_guest = models.BooleanField(default=False)
    is_host = models.BooleanField(default=False)
    language = models.CharField(max_length=2)


class Host(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    host_field = models.CharField(max_length=500)   


class Guest(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    guest_field = models.BooleanField(null=False)

在settings.py中:

AUTH_USER_MODEL = 'path.to.User'

创建新用户时会插入来宾或主机记录:

  user = User.objects.create_user(...)

  if is_host:
        Host.objects.create(user=user)
  else:
        Guest.objects.create(user=user)

我很欣赏我可以检测到请求对象中的用户“类型”(使用request.user.is_host)。

通过扩展用户类,您还可以使用email字段进行登录,并使其唯一:

class User(AbstractUser):
    [...]
    email = models.EmailField(unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

如果在生产中一次选择了在用户模型中添加字段,则有可能设置了自定义用户模型。

否则,您将被配置文件所困扰,因此,我建议您遵循Django的准则,并始终扩展用户类,即使您不需要它也是如此。