29

我发现有关是否使用OneToOneField(User)或何时通过扩展 Django User 模型来ForeignKey(User, unique=True)创建模型的信息相互矛盾。UserProfile

使用这个更好吗?:

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)

或这个?:

class UserProfile(models.Model):
    user = models.OneToOneField(User)

Django Doc指定OneToOneField,而Django Book 示例使用ForeignKey.

James Bennett也有两篇博客文章也提供了相互矛盾的例子:

ForeignKey在前一篇文章中,Bennett 提供了他改用 using而不是 的一些原因OneToOneField,但我不太明白,尤其是当我看到其他推荐相反的帖子时。

我很想知道你的偏好和原因。或者,它甚至重要吗?

4

3 回答 3

19

文章中给出的唯一真正原因是它可以设置为管理页面将同时显示和User中的字段。这可以用一点点肘部油脂来复制,所以除非你沉迷于在管理页面中显示它而没有任何工作以牺牲一点清晰为代价(“我们可以为每个用户创建多个配置文件?!哦,不,等等,它是独一无二的。”)我会用.UserUserProfileOneToOneFieldOneToOneField

于 2010-07-11T05:08:21.923 回答
7

除了管理页面内联之外,该解决方案的另一个原因ForeignKey是它允许您在使用反向关系访问对象时使用正确的默认数据库管理器。考虑来自这个子类管理器片段的例子。假设Post示例中的类定义如下所示:

class Post(ParentModel):
    title = models.CharField(max_length=50)
    onetoone = models.ForeignKey(SomeModel, unique=True)

    children = ChildManager()
    objects = models.Manager()

通过调用somemodel_instance.post_set.all()[0],您可以Post通过将第一个(默认)管理器定义为ChildManager. 另一方面,OneToOneField通过调用,somemodel_instance.post您可以获得Post类实例。您总是可以调用somemodel_instance.post.subclass_object并获得相同的结果,但默认管理器可以执行任何其他类型的技巧,并且FK解决方案很好地隐藏了它们。

如果您拥有并且可以修改自定义管理器代码,则可以使用该use_for_related_fields属性而不是使用 FK 代替合法的 1to1 字段,但由于自动管理器的一些我不知道的滋扰,即使这样也可能失败。据我记得,在上面的例子中它会失败。

于 2010-08-09T17:02:28.627 回答
5

通常不使用OneToOneField与反向关系相关的其他原因:当您使用通过OneToOneField您获得模型实例定义的反向关系时,与反向关系相反,Manager因此ForeignKey总是存在数据库命中。如果您在反向关系(通过)上做一些通用的事情_meta.get_all_related_objects()并且不知道也不关心您是否会全部使用它们,这将是昂贵的。

于 2010-11-17T15:15:56.423 回答