在 Django 的模型(models)中,可以通過外鍵(ForeignKey)關聯到另一個模型的某個特定屬性(字段)
在 Django 的模型(models)中,可以通過外鍵(ForeignKey)關聯到另一個模型的某個特定屬性(字段),但需滿足一定的條件。以下是具體實現方式和注意事項:
1. 外鍵默認行為
默認情況下,Django 的 ForeignKey 會關聯到目標模型的主鍵(通常是 id 字段)。例如:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE) # 默認關聯到 Author.id
此時,Book.author 字段存儲的是 Author 模型的主鍵值(id)。
2. 指定關聯到目標模型的特定字段
如果希望外鍵關聯到目標模型的非主鍵字段,需滿足以下條件:
-
目標字段必須是唯一的(
unique=True),否則會引發數據庫約束錯誤。 -
使用
to_field參數指定目標字段。
示例
class UserProfile(models.Model):
username = models.CharField(max_length=50, unique=True) # 必須是唯一字段
email = models.EmailField()
class Post(models.Model):
author = models.ForeignKey(
UserProfile,
to_field="username", # 關聯到 UserProfile.username 字段
on_delete=models.CASCADE,
)
title = models.CharField(max_length=100)
此時,Post.author 字段存儲的是 UserProfile.username 的值(而不是 id)。
3. 通過外鍵訪問目標模型的屬性
即使外鍵關聯到主鍵字段,也可以通過 Django ORM 直接訪問目標模型的任意屬性。例如:
# 獲取一本書的作者名
book = Book.objects.get(id=1)
author_name = book.author.name # 直接訪問 Author.name 字段
# 查詢所有作者名為 "Alice" 的書
books = Book.objects.filter(author__name="Alice")
這里的 author__name 語法表示通過外鍵 author 訪問關聯模型 Author 的 name 字段。
4. 反向查詢與 related_name
如果需要在目標模型中反向查詢關聯對象,可以使用 related_name:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name="books", # 反向查詢名稱
)
title = models.CharField(max_length=100)
通過 related_name,可以直接從 Author 反向查詢所有關聯的 Book:
author = Author.objects.get(name="Alice")
books = author.books.all() # 獲取 Alice 的所有書
5. 關聯到非唯一字段的替代方案
如果目標字段不是唯一的,無法直接通過 to_field 關聯,但可以通過以下方式間接實現:
(1) 使用 OneToOneField
如果關聯關系是一對一的,可以使用 OneToOneField:
class UserProfile(models.Model):
username = models.CharField(max_length=50) # 無需唯一
email = models.EmailField()
class UserAccount(models.Model):
profile = models.OneToOneField(
UserProfile,
on_delete=models.CASCADE,
related_name="account",
)
(2) 使用 ManyToManyField
如果關聯關系是多對多的,可以使用 ManyToManyField:
class Tag(models.Model):
name = models.CharField(max_length=50)
class Article(models.Model):
tags = models.ManyToManyField(Tag)
6. 性能優化
通過外鍵訪問關聯模型的屬性時,可以使用 select_related 或 prefetch_related 減少數據庫查詢次數:
# 避免 N+1 查詢問題
books = Book.objects.select_related("author").all()
for book in books:
print(book.author.name) # 單次查詢完成
總結
| 場景 | 實現方式 |
|---|---|
| 關聯到目標模型的主鍵 | 默認行為,無需額外參數 |
| 關聯到目標模型的唯一字段 | 使用 to_field="field_name" |
| 訪問目標模型的屬性 | 直接通過 obj.foreignkey.field 或查詢中的 foreignkey__field 語法 |
| 反向查詢關聯對象 | 使用 related_name |
| 關聯到非唯一字段 | 改用 OneToOneField 或 ManyToManyField,或通過中間表實現自定義邏輯 |
通過合理使用 Django 的 ORM 功能,可以靈活地定義模型間的關聯關系,并高效地操作數據。

浙公網安備 33010602011771號