Django:扩展用户时,最好使用 OneToOneField(User) 或 ForeignKey(User, unique=True)?
Posted
技术标签:
【中文标题】Django:扩展用户时,最好使用 OneToOneField(User) 或 ForeignKey(User, unique=True)?【英文标题】:Django: When extending User, better to use OneToOneField(User) or ForeignKey(User, unique=True)? 【发布时间】:2011-03-14 09:35:07 【问题描述】:在通过扩展 Django 用户模型创建 UserProfile
模型时,我发现关于是否使用 OneToOneField(User)
或 ForeignKey(User, unique=True)
的信息相互矛盾。
用这个更好吗?:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
还是这个?:
class UserProfile(models.Model):
user = models.OneToOneField(User)
Django Doc 指定OneToOneField
,而Django Book example 使用ForeignKey
。
James Bennett 也有两篇博客文章也提供了相互冲突的示例:
Extending the User Model User Registration在上一篇文章中,Bennett 提供了他改用 ForeignKey
而不是 OneToOneField
的一些原因,但我不太明白,尤其是当我看到其他推荐相反的帖子时。
我很想知道您的偏好以及原因。或者,它甚至重要吗?
【问题讨论】:
我在 Bennett 的第一篇关于用户配置文件的文章中没有看到任何内容。 @Ignacio - 抱歉,我添加了指向错误文章的链接。应该是他关于“扩展用户模型”的帖子。我已经更正了链接。感谢您指出这一点。 对我来说,***.com/questions/5870537/… 更清晰易懂 【参考方案1】:文章中给出的唯一真正原因是它可以设置为User
的管理页面将同时显示User
和UserProfile
中的字段。这可以用OneToOneField
和一点点肘部油脂来复制,所以除非你沉迷于在管理页面中显示它而没有任何工作以牺牲一点清晰度(“我们可以为每个用户创建多个配置文件?!哦,不,等等,它是独一无二的。”)我会使用 OneToOneField
。
【讨论】:
【参考方案2】:除了管理页面内联之外,ForeignKey
解决方案的另一个原因是它允许您在以反向关系访问对象时使用正确的默认数据库管理器。考虑来自此subclasses manager snippet 的示例。假设示例中的 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]
,您可以通过将第一个(默认)管理器定义为ChildManager
来获得Post
类的所需子类对象。另一方面,对于OneToOneField
,通过调用somemodel_instance.post
,您将获得Post
类实例。您可以随时调用 somemodel_instance.post.subclass_object
并获得相同的结果,但默认管理器可以做任何其他类型的技巧,FK
解决方案很好地隐藏了它们。
如果您拥有并且可以修改自定义管理器代码,则可以使用 use_for_related_fields
属性而不是使用 FK 代替合法的 1to1 字段,但即使这样也可能会因为自动管理器的一些不为人知的滋扰而失败.据我记得,在上面的例子中它会失败。
【讨论】:
【参考方案3】:通常不使用与反向关系相关的OneToOneField
的其他原因:当您使用通过OneToOneField
定义的反向关系时,您会得到一个模型实例,这与Manager
的ForeignKey
反向关系相反,因此有总是一个 DB 命中。如果您在反向关系上做一些通用的事情(通过_meta.get_all_related_objects()
)并且不知道也不关心您是否会全部使用它们,那么这是昂贵的。
【讨论】:
以上是关于Django:扩展用户时,最好使用 OneToOneField(User) 或 ForeignKey(User, unique=True)?的主要内容,如果未能解决你的问题,请参考以下文章
Django解决扩展用户表时,后台Admin显示密码为明文的问题