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

Django OneToOneFieldForeignKey的区别是什么?

178899 次浏览

ForeignKey是一个多对一关系。因此,Car对象可能有许多Wheel的实例。因此,每个Wheel将有一个ForeignKey到它所属的CarOneToOneField类似于Engine的实例,其中Car对象有一个且只有一个最多对象。

OneToOneField(SomeModel)ForeignKey(SomeModel, unique=True)之间的差异,如The Definitive Guide to Django .所述:

一对一字段

一对一的关系。从概念上讲,这类似于ForeignKeyunique=True,但是&;反向&;关系的一侧将直接返回单个对象。

OneToOneField &;reverse&;关系,一个ForeignKey "反转;关系返回一个QuerySet

例子

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

  1. Car模型使用OneToOneField(Engine)
  2. Car2模型使用ForeignKey(Engine2, unique=True)

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

# EYZ0例子

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

ForeignKeyunique=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(一对一)在面向对象中实现了组合的概念,而ForeignKey(一对多)则与聚合有关。

当您访问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而生成的。

学习新事物的最好和最有效的方法是看和研究现实世界的实际例子。假设您想在django中构建一个博客,记者可以在这里撰写和发布新闻文章。这家在线报纸的所有者希望允许他的每个记者发表尽可能多的文章,但不希望不同的记者为同一篇文章工作。这意味着当读者去阅读一篇文章时,他们只能在文章中看到一个作者。

例如:John的文章,Harry的文章,Rick的文章。你不能有Harry &因为老板不希望两个或两个以上的作者写同一篇文章。

如何在django的帮助下解决这个问题?解决这个问题的关键是django ForeignKey

下面是完整的代码,可以用来实现我们老板的想法。

from django.db import models


# Create your models here.


class Reporter(models.Model):
first_name = models.CharField(max_length=30)


def __unicode__(self):
return self.first_name




class Article(models.Model):
title = models.CharField(max_length=100)
reporter = models.ForeignKey(Reporter)


def __unicode__(self):
return self.title

运行python manage.py syncdb来执行sql代码,并在数据库中为应用程序构建表。然后使用python manage.py shell打开一个python shell。

创建Reporter对象R1。

In [49]: from thepub.models import Reporter, Article


In [50]: R1 = Reporter(first_name='Rick')


In [51]: R1.save()

创建Article对象A1。

In [5]: A1 = Article.objects.create(title='TDD In Django', reporter=R1)


In [6]: A1.save()

然后使用下面的代码段获取报告器的名称。

In [8]: A1.reporter.first_name
Out[8]: 'Rick'

现在通过运行以下python代码创建Reporter对象R2。

In [9]: R2 = Reporter.objects.create(first_name='Harry')


In [10]: R2.save()

现在尝试将R2添加到Article对象A1。

In [13]: A1.reporter.add(R2)

它不起作用,你会得到一个AttributeError,说'Reporter'对象没有属性'add'。

正如您所看到的,一个Article对象不能与多个Reporter对象相关。

R1呢?我们可以给它附加多个Article对象吗?

In [14]: A2 = Article.objects.create(title='Python News', reporter=R1)


In [15]: R1.article_set.all()
Out[15]: [<Article: Python News>, <Article: TDD In Django>]

这个实例向我们展示了django ForeignKey是用来定义多对一关系的。

OneToOneField用于创建一对一的关系。

我们可以在上面的models.py文件中使用reporter = models.OneToOneField(Reporter),但它在我们的例子中并不有用,因为作者将无法发布多篇文章。

每次要发布一篇新文章时,都必须创建一个新的Reporter对象。这很浪费时间,不是吗?

我强烈建议您尝试使用OneToOneField的示例,并了解其中的差异。我很确定在这个例子之后,你会完全知道django OneToOneField和django ForeignKey之间的区别。

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

models.AutoField(primary_key=True)

而是使用OneToOneField作为主键(例如,想象UserProfile模型):

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

OneToOneField:如果第二个表与

table2_col1 = models.OneToOneField(table1,on_delete=models.CASCADE, related_name='table1_id')

Table2将只包含一条对应于table1的pk值的记录,即table2_col1将有一个等于表pk的唯一值

table2_col1 == models.ForeignKey(table1, on_delete=models.CASCADE, related_name='table1_id')

Table2可以包含多条与table1的pk值相对应的记录。

ForeignKey允许你接收子类,它是另一个类的定义,但OneToOneFields不能这样做,它不能附加到多个变量

绘制项目之间关系的最简单方法是用简单的语言理解它们。例子

一个用户可以有很多辆车,但一辆车只能有一个车主。建立此关系后,应将外键用于关系较多的项上。在这种情况下,是汽车。这意味着您将在cars中包含user作为外键

一对一的关系很简单。说一个男人和一颗心。一个人只有一颗心,而一颗心只能属于一个人

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

.
我也对这两个字段的用法感到困惑。 让我举一个例子来理解它们的用法,因为我最近遇到了这个问题,并意识到这两个字段的用法

我有一个模型,像这样

from django.contrib.auth.models import User
from django.db import models




class Attendance(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, default="", null=True)
date = models.CharField(max_length=11)


def __int__(self):
return self.id
现在的问题是,我不能用同一个用户创建多个对象, 也就是说,同一个用户将在多个日子里出席会议。因此,相同用户的多个对象 但是OneToOne字段不允许我这样做。 # EYZ0 < / p >

所以我把模型改成-

from django.contrib.auth.models import User
from django.db import models




class Attendance(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default="", null=True)
date = models.CharField(max_length=11)


def __int__(self):
return self.id

现在它工作得很好,我可以标记一个用户在多天的出席。

这就是区别所在,OneToOne字段不允许你用同一个用户创建多个对象(举个例子),但是使用ForeignKey是可以的。