Django中的OneToOneField和ForeignKey有什么区别?


当前回答

OneToOneField(一对一)在面向对象中实现了组合的概念,而ForeignKey(一对多)则与聚合有关。

其他回答

ForeignKey是一个多对一的关系。因此,Car对象可能有许多Wheel实例。因此,每个Wheel都有一个它所属的Car的ForeignKey。OneToOneField就像Engine的一个实例,其中Car对象最多只有一个。

在Django最终指南中,OneToOneField(SomeModel)和ForeignKey(SomeModel, unique=True)的区别如下:

一对一字段 一对一的关系。从概念上讲,这类似于带有unique=True的ForeignKey,但是关系的“反向”端将直接返回单个对象。

与OneToOneField“反向”关系相反,ForeignKey“反向”关系返回一个QuerySet。

例子

例如,如果我们有以下两个模型(完整的模型代码如下):

汽车模型使用OneToOneField(引擎) Car2模型使用ForeignKey(Engine2, unique=True)

在python manage.py shell中执行以下命令:

一对一字段的例子

>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car
<Car: Audi>

ForeignKey with unique=True示例

>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
>>> e2.car2_set.all()
[<Car2: Mazda>]

模型代码

from django.db import models

class Engine(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car(models.Model):
    name = models.CharField(max_length=25)
    engine = models.OneToOneField(Engine)

    def __unicode__(self):
        return self.name

class Engine2(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car2(models.Model):
    name = models.CharField(max_length=25)
    engine = models.ForeignKey(Engine2, unique=True, on_delete=models.CASCADE)

    def __unicode__(self):
        return self.name

此外,OneToOneField可用作主键以避免键重复。可能没有隐式/显式autofield

models.AutoField(primary_key=True)

但是使用OneToOneField作为主键(假设UserProfile模型为例):

user = models.OneToOneField(
    User, null=False, primary_key=True, verbose_name='Member profile')

当您访问OneToOneField时,您将获得您查询的字段的值。在这个例子中,图书模型的title字段是一个OneToOneField:

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

当你访问一个ForeignKey时,你得到了相关的模型对象,然后你可以对它进行进一步的查询。在这个例子中,同一个图书模型的'publisher'字段是一个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而生成的。

OneToOneField(例如:一辆车有一个车主) ForeignKey(OneToMany)(例如:一个餐厅有很多项目)