Ton*_*nta 29 django django-models django-profiles django-users
我正在通过扩展Django User模型找到有关是否使用OneToOneField(User)或ForeignKey(User, unique=True)创建UserProfile模型的相互矛盾的信息.
使用它更好吗?:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
Run Code Online (Sandbox Code Playgroud)
或这个?:
class UserProfile(models.Model):
user = models.OneToOneField(User)
Run Code Online (Sandbox Code Playgroud)
在Django的文件规定OneToOneField,而Django的书例子使用ForeignKey.
詹姆斯贝内特也有两篇博客文章,也提供了相互矛盾的例子:
在前一篇文章中,Bennett提供了一些原因,为什么他转而使用ForeignKey而不是OneToOneField,但我不太明白,特别是当我看到推荐相反的其他帖子时.
我很想知道你的偏好和原因.或者,它甚至重要吗?
Ign*_*ams 18
在文章中给出的唯一的真正原因是,它可以设置,使管理员页面User会同时显示在田野User和UserProfile.这可以OneToOneField用一点点肘部油脂来复制,所以除非你沉迷于在管理页面中显示它而没有工作,只需要有点清晰("我们可以为每个用户创建多个配置文件?!哦不,等等,这是独特的.")我会用OneToOneField.
除了管理页面内联之外,该ForeignKey解决方案的其他原因是它允许您在以反向关系访问对象时使用正确的默认数据库管理器.请考虑此子类管理器代码段中的示例.假设Post示例中的类定义如下所示:
class Post(ParentModel):
title = models.CharField(max_length=50)
onetoone = models.ForeignKey(SomeModel, unique=True)
children = ChildManager()
objects = models.Manager()
Run Code Online (Sandbox Code Playgroud)
通过调用somemodel_instance.post_set.all()[0],您可以Post通过将第一个(默认)管理器定义为a来获得所需的类的子类对象ChildManager.另一方面,OneToOneField通过调用,somemodel_instance.post您获得Post类实例.您可以随时调用somemodel_instance.post.subclass_object并获得相同的结果,但默认管理器可以执行任何其他类型的技巧,并且FK解决方案可以很好地隐藏它们.
如果您拥有并且可以修改自定义管理器代码,则可以使用该use_for_related_fields属性而不是使用FK代替合法的1to1字段,但即使这样也会失败,因为我对自动管理器的一些不为人知.据我记得,在上面的例子中它将失败.
其他原因一般不使用OneToOneField与反向关系:当您使用通过定义反向关系,OneToOneField你会得到一个模型实例,违背Manager了ForeignKey反向关系,因此总有一个DB命中.如果你在反向关系(通过_meta.get_all_related_objects())上做一些通用的东西,并且不知道和关心你是否将全部使用它们,这是昂贵的.