在 Django 中反向查詢外來鍵

Vaibhav Vaibhav 2021年8月10日
在 Django 中反向查詢外來鍵

Django 是一種高效的 Web 開發框架,可簡化 Web 應用程式的建立。Django 可以輕鬆處理身份驗證和授權、建立 HTML 模板、處理靜態檔案、與資料庫互動以及對它們執行 CRUD 操作。

說到資料庫,Django 簡化了你在使用資料庫時可以進行的大多數查詢。一個這樣的查詢是反向查詢;一個例子是當我們必須獲取一個表的所有物件時,這些物件引用同一表或不同模型的特定記錄。

本文將展示在 Django 中執行外來鍵反向查詢是多麼簡單。

Django 模型中的反向查詢

在我們進入實際步驟之前,我們需要一些模型或表格進行演示。我們將考慮兩個實體:教師和學生。學生有兩種型別的老師;班主任和最喜歡的老師。Student 模型引用了 Teacher 模型。

from django.db import models


class Teacher(models.Model):
    name = models.CharField(max_length=200)
    subject = models.CharField(max_length=200)


class Student(models.Model):
    name = models.CharField(max_length=200)
    classTeacher = models.ForeignKey(
        Teacher, on_delete=models.SET_NULL, null=True, related_name="classTeacherOf"
    )
    favouriteTeacher = models.ForeignKey(
        Teacher, on_delete=models.SET_NULL, null=True, related_name="favouriteTeacherOf"
    )

Student 模型的兩個欄位引用了 Teacher 模型。在 Django 中,當多次引用同一個模型時,我們必須為所有欄位提供一個 related_name,因為 Django 的單個引用欄位的預設 related_name 會與其他引用欄位發生衝突。否則,Django 將丟擲異常。

related_name 是我們用於反向查詢的內容。通常,為所有外來鍵提供 related_name 是一個好習慣,而不是使用 Django 的預設相關名稱。

示例 1

我們有一位老師,他的 id1。如果我們必須讓所有有這個人作為班主任的學生,我們將執行以下操作:

teacher = Teacher.objects.get(id=1)
students = teacher.classTeacherOf.all()
print(students)  # A QuerySet of Student objects

請注意我們如何使用 related_nameteacher.classTeacherOf 是一個管理器物件,這意味著我們可以在其上呼叫 all()filter()exclude() 等方法。

示例 2

我們有一位老師,他的 id6。如果我們必須讓所有認為這位老師是他們最喜歡的老師的學生,我們會這樣做:

teacher = Teacher.objects.get(id=6)
students = teacher.favouriteTeacherOf.all()
print(students)  # A QuerySet of Student objects

示例 3

我們有一位老師,他的 id25。如果我們要檢查這個老師是否是一個 id5 的學生的班主任,我們將做如下操作:

teacher = Teacher.objects.get(id=25)
student = teacher.classTeacherOf.filter(id=5)
print(student)  # A QuerySet of either 1 or 0 Student

請注意,如果在反向查詢中沒有找到物件,則返回一個空的 QuerySet

作者: Vaibhav Vaibhav
Vaibhav Vaibhav avatar Vaibhav Vaibhav avatar

Vaibhav is an artificial intelligence and cloud computing stan. He likes to build end-to-end full-stack web and mobile applications. Besides computer science and technology, he loves playing cricket and badminton, going on bike rides, and doodling.