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


当前回答

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

其他回答

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

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值相对应的记录。

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

我有一个模型,像这样

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

现在这个的问题是我不能用同一个用户创建多个对象, 也就是说,同一个用户将在多个日子里出席会议。因此,同一个用户有多个对象。

但是一对一领域不允许我这么做。 参考图片

所以我把模型改成-

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是可以的。

此外,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而生成的。