Django:扩展User时,最好使用OneToOneField(User)或ForeignKey(User,unique=True)?
我发现在创建 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
本文中给出的唯一真正原因是,可以对其进行设置,以便
User
的管理页面将显示User
和UserProfile
中的字段代码>.这可以使用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 inUser
andUserProfile
. This can be replicated with aOneToOneField
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 useOneToOneField
.除了管理页面内联之外,
ForeignKey
解决方案的另一个原因是,当通过反向关系访问对象时,它允许您使用正确的默认数据库管理器。请考虑此子类管理器片段中的示例。假设示例中的Post
类定义如下所示:通过调用
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 thePost
class definition from the example looks like this:By calling
somemodel_instance.post_set.all()[0]
, you get the desired subclasses objects of thePost
class as indicated by defining the first (default) manager as aChildManager
. On the other hand, withOneToOneField
, by callingsomemodel_instance.post
you get thePost
class instance. You can always callsomemodel_instance.post.subclass_object
and get the same result, but the default manager could do any other sort of tricks and theFK
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.通常不使用与反向关系相关的
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 viaOneToOneField
you get an model instance, contrary toManager
forForeignKey
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.