Django `_set` 用法筆記(ForeignKey 反向關聯)

🔗 Django _set 用法筆記(ForeignKey 反向關聯)

✅ 基本觀念:一對多關係(ForeignKey)

假設有下列兩個 Model:

class Interview(models.Model):
    title = models.CharField(max_length=100)

class Comment(models.Model):
    interview = models.ForeignKey(Interview, on_delete=models.CASCADE)
    content = models.TextField()

這裡代表:

  • 一個 Interview 可以有多個 Comment
  • Comment 是「多」方,透過 ForeignKey 指向「一」方的 Interview

↻ 反向關聯:使用 _set

Django 會自動在一方的 model 加上一個反向屬性,名稱預設是:

<related_model_name>_set

所以可以這樣用:

interview.comment_set.all()  # 查出這個 interview 底下的所有 comment
interview.comment_set.create(content='你好')  # 新增一筆 comment 自動連結該 interview

📛 注意:預設反向屬性的命名方式

預設情況下,Django 會以「小寫 model 名稱 + _set」為一方建立反向屬性。

例如:

class Comment(models.Model):
    interview = models.ForeignKey(Interview, on_delete=models.CASCADE)
  • 這會讓你能夠使用 interview.comment_set 來取得該 interview 所有的 comment。
  • 若 model 名稱為 Message,則會是 article.message_set

若希望有更語意化的名稱,建議加上 related_name(見下方)。


✍️ 常見用法整理:

# 取得所有 comment
comments = interview.comment_set.all()

# Interview 角度
# 建立一筆新的 comment 並與 interview 關聯
interview.comment_set.create(content=req.POST['content'])

# Comment 角度
Comment.objects.create(interview=interview, content=req.POST['content'])

💡 如何自訂反向名稱(最佳實踐)

為了讓語意更清楚,可以在 ForeignKey 中加上 related_name

class Comment(models.Model):
    interview = models.ForeignKey(
        Interview,
        on_delete=models.CASCADE,
        related_name='comments'  # 自訂名稱
    )

就能這樣使用:

interview.comments.all()
interview.comments.create(content='加油!')

💬 面試回答(Q&A)

Q: Django 中如何透過 ForeignKey 建立一對多關係,並如何查詢/建立子資料?
A:

在多方的 model 使用 ForeignKey 連到一方,並使用 Django 提供的反向屬性 <model>_set 來存取。例如 interview.comment_set.create(...) 可以新增一筆資料,同時建立關聯。如果加上 related_name 可以讓語意更清楚,如 interview.comments.create(...)