Django ORM“.” vs "_" 访问外键id时

Tia*_*Liu 2 django orm foreign-keys

class Author(models.Model):
    name = models.CharField(max_length=120)

class Book(models.Model):
    name = models.CharField(max_length=20)
    author= models.ForeignKey(Author)
Run Code Online (Sandbox Code Playgroud)

考虑这两个模型。当我访问这个外键时,这两种方式有什么区别:

id= Book.objects.get(pk=1).author.id
id= Book.objects.get(pk=1).author_id
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 6

语义没有区别。但随着版本author_id更有效率author.id

如果你定义了一个外键,那么你实际上一次定义了两个 Django 字段: the fieldname,它是对你引用的模型的模型对象的引用,以及一个 field fieldname_id,它包含对象的主键的值你提到的。只有后者被存储在数据库中(因为前者可以通常不被存储在数据库中)。

请注意,如果您想访问.author,通常这意味着您必须执行额外的查询,因为除非显式加载 ,否则这些关系.select_related(..)不会立即加载,而是延迟加载:它需要额外的数据库来获取相关Author对象。当然,一个额外的查询无关紧要,但是如果您例如在for循环中执行此操作,那么这将导致n+1问题:您将需要 1 个查询来获取书籍,并且需要n 个查询来获取每本书的作者。

请注意,如前所述,有多种方法可以减少使用prefetch_related, 和查询相关对象的数量select_related。但它仍然会导致传输更多的数据。如果你在感兴趣的主键Author,那么你可以使用author_id,不需要这种额外获取。