Django - 使用配置文件扩展用户模型,但也使用不同的用户类型
Django - extend the User model with a Profile but also different user kind
我想在 Django (2.2) 中扩展用户模型,并将其与具有特定字段的主机和来宾实体组合。
在 official documentation 中,建议创建一个 "Profile" class,其中包含引用用户主键的 OneToOne 字段。
我可以看到 3 种方法:
解决方案一:配置文件、Host 和 Guest 模型:
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:配置文件模型(包含 Guest 和 Host 字段)
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)
所有这些解决方案都有效。
我的问题是:"Which one is the smartest, all things considered"(更少的数据库访问、更少的代码编写、更容易维护、更少的限制等。)
我会提出一种 4:th 方法,使用带有抽象模型的混合。这会将抽象模型的字段派生到您应用它的那些字段。这样你就不需要重写代码,仍然适用于不同的模型:
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)
在深入研究 Django 的文档并阅读解释如何在 Django 中实现多用户类型的 article mentioned by @sam 之后,我找到了答案。
Django doc里面写着"it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you".
这是我的情况:
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
)中检测到用户 "type"。
通过扩展用户class,您也可以使用email
字段进行登录,并使其唯一:
class User(AbstractUser):
[...]
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
如果您在生产环境中选择在用户模型中添加字段,那么如果您已经设置了自定义用户模型,则有可能。
否则你会被配置文件困住,所以我建议你遵循 Django 的指导方针并始终扩展用户 class,即使你不需要它(还)。
我想在 Django (2.2) 中扩展用户模型,并将其与具有特定字段的主机和来宾实体组合。
在 official documentation 中,建议创建一个 "Profile" class,其中包含引用用户主键的 OneToOne 字段。
我可以看到 3 种方法:
解决方案一:配置文件、Host 和 Guest 模型:
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:配置文件模型(包含 Guest 和 Host 字段)
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)
所有这些解决方案都有效。
我的问题是:"Which one is the smartest, all things considered"(更少的数据库访问、更少的代码编写、更容易维护、更少的限制等。)
我会提出一种 4:th 方法,使用带有抽象模型的混合。这会将抽象模型的字段派生到您应用它的那些字段。这样你就不需要重写代码,仍然适用于不同的模型:
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)
在深入研究 Django 的文档并阅读解释如何在 Django 中实现多用户类型的 article mentioned by @sam 之后,我找到了答案。
Django doc里面写着"it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you".
这是我的情况:
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
)中检测到用户 "type"。
通过扩展用户class,您也可以使用email
字段进行登录,并使其唯一:
class User(AbstractUser):
[...]
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
如果您在生产环境中选择在用户模型中添加字段,那么如果您已经设置了自定义用户模型,则有可能。
否则你会被配置文件困住,所以我建议你遵循 Django 的指导方针并始终扩展用户 class,即使你不需要它(还)。