【问题标题】:Difference between ForeignKey(User, unique=True) and OneToOneField [duplicate]ForeignKey(User, unique=True) 和 OneToOneField 之间的区别 [重复]
【发布时间】:2012-04-14 11:58:21
【问题描述】:

Django 中的models.ForeignKey(Modelname, unique=True)models.OneToOneField 有什么不同?

我应该在哪里使用models.OneToOneFieldmodels.ForeignKey(Modelname, unique=True)

【问题讨论】:

  • @alan Wasn't enough clarification in other answers like this Alasdir's Answer很好地阐明了这个概念

标签: django django-models


【解决方案1】:

OneToOneField 与带有unique=TrueForeignKey 非常相似。除非你在做多表继承,在这种情况下你必须使用OneToOneField,唯一真正的区别是访问相关对象的api。

Django docs 中写道:

从概念上讲,这类似于 ForeignKeyunique=True,但关系的“反向”端将直接返回单个对象。

让我们用一个例子来说明这意味着什么。考虑两个模型,PersonAddress。我们假设每个人都有一个唯一的地址。

class Person(models.Model):
    name = models.CharField(max_length=50)
    address = models.ForeignKey('Address', unique=True)

class Address(models.Model):
    street = models.CharField(max_length=50)

如果以人开头,则可以轻松访问地址:

address = person.address

但是,如果您以地址开头,则必须通过 person_set 经理来获取此人。

person = address.person_set.get() # may raise Person.DoesNotExist

现在让我们将ForeignKey 替换为OneToOneField

class Person(models.Model):
    name = models.CharField(max_length=50)
    address = models.OneToOneField('Address')

class Address(models.Model):
    street = models.CharField(max_length=50)

如果以人开头,同样可以访问地址:

address = person.address

现在,我们可以更轻松地从该地址访问此人。

person = address.person # may raise Person.DoesNotExist

【讨论】:

  • 可能值得注意的是,Django 会为具有 unique=True 的 ForeignKey 字段生成以下警告:“提示:ForeignKey(unique=True) 通常由 OneToOneField 提供更好的服务”
【解决方案2】:

当您访问OneToOneField 时,您将获得所查询字段的值。在此示例中,图书模型的“标题”字段是 OneToOneField

>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'

当您访问ForeignKey 时,您将获得相关的模型对象,然后您可以对其执行进一步的查询。在此示例中,同一图书模型的“发布者”字段是 ForeignKey(与 Publisher 类模型定义相关):

>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'

ForeignKey 字段查询也以另一种方式工作,但由于关系的非对称性质,它们略有不同。

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]

在幕后,book_set 只是一个QuerySet,可以像任何其他QuerySet 一样进行过滤和切片。属性名称 book_set 是通过将小写模型名称附加到 _set 来生成的。 我希望这有助于说明所创建的关系之间的差异。

【讨论】:

    猜你喜欢
    • 2011-03-14
    • 1970-01-01
    • 2011-08-17
    • 2018-06-05
    • 2014-12-07
    • 2023-03-14
    • 2015-09-04
    • 2015-10-18
    相关资源
    最近更新 更多