Django:扩展User时,最好使用OneToOneField(User)或ForeignKey(User,unique=True)?

发布于 2024-09-08 19:33:55 字数 1234 浏览 14 评论 0原文

我发现在创建 UserProfile 模型时是否使用 OneToOneField(User)ForeignKey(User, unique=True) 的信息存在冲突扩展 Django 用户模型。

使用这个更好吗?:

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 也有两篇博客文章提供了相互冲突的示例:

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

我很想知道您的偏好以及原因。或者说,这还重要吗?

I'm finding conflicting information on whether to use OneToOneField(User) or ForeignKey(User, unique=True) when creating a UserProfile model by extending the Django User model.

Is it better to use this?:

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

or this?:

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

The Django Doc specifies OneToOneField, while the Django Book example uses ForeignKey.

James Bennett also has two Blog posts that providing conflicting examples as well:

In the former post, Bennett provides some reasons why he switched to using ForeignKey instead of OneToOneField, but I don't quite get it, especially when I see other posts that recommend the opposite.

I'm curious to know your preference and why. Or, does it even matter?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

岁月染过的梦 2024-09-15 19:33:55

本文中给出的唯一真正原因是,可以对其进行设置,以便 User 的管理页面将显示 UserUserProfile 中的字段代码>.这可以使用 OneToOneField 进行复制,但需要一点点努力,所以除非您沉迷于在管理页面中显示它,而无需任何工作,但会牺牲一点清晰度(“我们可以创建多个每个用户的配置文件?!哦,不,等等,它被设置为唯一的。”)我会使用 OneToOneField

The only real reason given in the article is that it can be set up so that the admin page for User will show both the fields in User and UserProfile. This can be replicated with a OneToOneField with a little elbow grease, so unless you're addicted to showing it in the admin page with no work at the cost of a bit of clarity ("We can create multiple profiles per user?! Oh no, wait, it's set unique.") I'd use OneToOneField.

奈何桥上唱咆哮 2024-09-15 19:33:55

除了管理页面内联之外,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],您可以获得 somemodel_instance.post_set.all()[0] 所需的子类对象code>Post 类,通过将第一个(默认)管理器定义为 ChildManager 来指示。另一方面,使用 OneToOneField,通过调用 somemodel_instance.post,您可以获得 Post 类实例。您始终可以调用 somemodel_instance.post.subclass_object 并获得相同的结果,但默认管理器可以执行任何其他类型的技巧,并且 FK 解决方案很好地隐藏了它们。

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

Besides the admin page inlines, other reason for the ForeignKey solution is that it allows you to use the correct, default DB manager when objects are accessed with a reverse relation. Consider example from this subclasses manager snippet. Let's say that the Post class definition from the example looks like this:

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

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

By calling somemodel_instance.post_set.all()[0], you get the desired subclasses objects of the Post class as indicated by defining the first (default) manager as a ChildManager. On the other hand, with OneToOneField, by calling somemodel_instance.post you get the Post class instance. You can always call somemodel_instance.post.subclass_object and get the same result, but the default manager could do any other sort of tricks and the FK solutions hides them nicely.

If you own and can modify the custom manager code you can use the use_for_related_fields attribute instead of using FK in place of legitimate 1to1 field, but even that can fail because of some not-known to me nuisances of the automatic managers. As far as I remember it will fail in the above example.

摘星┃星的人 2024-09-15 19:33:55

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

Other reason to generally not use the OneToOneField related to reverse relations: when you use reverse relations defined via OneToOneField you get an model instance, contrary to Manager for ForeignKey reverse relation and as a consequence there's always a DB hit. This is costly if you do some generic stuff on reverse relations (via _meta.get_all_related_objects()) and do not know and care if you will use them all or not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文