ForeignKey与扩展Django中的User类/模型之间的区别

时间:2015-07-28 07:51:37

标签: python django django-models relational-database

Django: When extending User, better to use OneToOneField(User) or ForeignKey(User, unique=True)?

我经历了这个线程,发现ForeignKey(带有unique=True)比OneToOneField更好,但是如何扩展类本身,即I.e.这是一个例子

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    # some additional fields

OR

class UserProfile(User):
    # some additional fields

这两种方法和利弊之间的区别以及我应该使用哪种方法?

编辑: 我也可以使用AbstractUser

from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    phone_no = models.CharField(max_length=10, blank=True)

然后在settings.py中提到AUTH_USER_MODEL = 'myapp.User'

主要关注的是,我应该使用什么方法,扩展类或ForeignKey?

重复:

What's the difference between OneToOne and Subclassing a model in Django

Django Model Inheritance versus OneToOne field

更多编辑

忘记ForeginKey或OneToOne,假设只存在这两个中的一个,现在将其与扩展/子类化方法进行比较

3 个答案:

答案 0 :(得分:1)

首先,很高兴知道目前有多种选择如何扩展Django用户模型。每个都有它的目的(但也有一些重叠)。 Django文档有点令人困惑,因为它似乎来自this有两个选项,即proxy或OneToOneField。但是,这与现有用户模型有关,因为文档中的更多内容涉及自定义用户模型。

因此在实践中有四种(常见的)方法来处理扩展用户模型:

  1. 代理模型(没有新的数据库字段,只是为了更改用户模型行为,即新订购,新方法等)。
  2. OneToOneField (现有Djang用户模型中需要额外的数据字段)。
  3. 使用 AbstractBaseUser (额外数据字段)自定义用户模型 需要,以及有关认证过程的具体要求, 例如使用emailaddress als id token而不是username)。
  4. 使用 AbstractUser 的自定义用户模型(需要额外的数据字段,没有 更改为身份验证)。
  5. 实现选项3和4需要进行全新的数据库迁移,因此这些只适用于新项目。

    This is a good link for more detail on this。我认为选项2和4最接近,因为两者都只想扩展以添加更多数据字段。 Writer似乎赞成选项2,但是当开始一个新项目时,选项4对我来说似乎更容易。在评论的某个地方,作者提到了无法升级到选项3和4的新Django版本的风险。似乎对我来说很牵强,但我无法说清楚。

答案 1 :(得分:0)

没有更好的方法可做,问题是如果你扩展AbstractUser你需要重新定义某些功能,这样它可能会更长,但你可以更好地控制你想对你的用户做什么。

在django上创建OneToOne字段默认用户更快,并且还允许您添加自己的用户自定义字段,但您可以直接使用自定义对象中的用户默认字段和用户的自定义字段:

from django.contrib.auth.models import User

class Employee(models.Model):
    user = models.OneToOneField(User)
    department = models.CharField(max_length=100)

你可以这样做:

>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department

所以这真的取决于你想做什么。例如,如果您想将邮件地址作为识别令牌(这是一个常见的例子,但您可以做更多的事情,请执行您的用户:p)。

Here是一个很好的解释(我将它放在用户身上,但是当你深入了解用户并对Django进行身份验证时,你可以阅读整个页面,这非常有趣。)

希望有所帮助。

答案 2 :(得分:0)

我对独特的FK与一对一的好处持怀疑态度,你可以使用fieldsets在管理员中实现类似的事情,所以我更希望有一个明确的一对一字段在模型上,使关系的性质更加明显。

您链接的重复问题并非特定于身份验证User模型,并且通常会讨论一对一与模型继承。从技术上讲,它们都是相同的(即模型继承使用一对一的字段)

所以最终选择归结为语义:你的相关模型是一个子类'另一个,或只是进一步相关信息的链接?

在auth User的情况下你会问自己:是否有一些额外的字段应该存在给所有用户(例如性别,脸书ID等)?或者你想从Django User模型中省略一些字段(例如使用唯一的电子邮件地址作为用户名)?

在这种情况下,显而易见的选择是扩展AbstractUser。如果您无法想象在用户个人资料模型上指定null=True,则应考虑延长AbstractUser

另一方面,可能有一些数据更类似于旧的UserProfile模型(看看在支持扩展AbstractUser之前旧版Django中的内容是如何支持的:{{3 }})

例如,您可能有不同类型的用户,这些用户可能有也可能没有某些额外的字段集。在这种情况下,与一个或多个配置文件的一对一链接可能是有意义的。模型。