外來鍵刪除操作
如果一個模型使用了外來鍵。那麼在對方那個模型被刪掉後,該進行什麼樣的操作。可以通過on_delete
來指定。可以指定的型別如下:
- CASCADE:級聯操作。如果外來鍵對應的那條資料被刪除了,那麼這條資料也會被刪除。
- PROTECT:受保護。即只要這條資料引用了外來鍵的那條資料,那麼就不能刪除外來鍵的那條資料。
- SET_NULL:設定為空。如果外來鍵的那條資料被刪除了,那麼在本條資料上就將這個欄位設定為空。如果設定這個選項,
前提是要指定這個欄位可以為空
。 - SET_DEFAULT:設定預設值。如果外來鍵的那條資料被刪除了,那麼本條資料上就將這個欄位設定為預設值。如果設定這個選項,前提是要指定這個欄位一個預設值。
- SET():如果外來鍵的那條資料被刪除了。那麼將會獲取SET函式中的值來作為這個外來鍵的值。SET函式可以接收一個可以呼叫的物件(比如函式或者方法),如果是可以呼叫的物件,那麼會將這個物件呼叫後的結果作為值返回回去。
- DO_NOTHING:不採取任何行為。一切全看資料庫級別的約束。
注意:以上這些選項只是Django級別
的,資料級別依舊是RESTRICT
!
表關係
表之間的關係都是通過外來鍵來進行關聯的。而表之間的關係,無非就是三種關係:一對一、一對多、多對多等。以下將討論一下三種關係的應用場景及其實現方式。
一對多
應用場景:比如文章和作者之間的關係。一個文章只能由一個作者編寫,但是一個作者可以寫多篇文章。文章和作者之間的關係就是典型的多對一的關係
實現方式:一對多,都是通過ForeignKey
來實現的。
class User(models.Model):
username = models.CharField(max_length=20)
password = models.CharField(max_length=100)
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey("User",on_delete=models.CASCADE)
那麼以後在給Article
物件指定category
,就可以使用以下程式碼來完成:
article = Article(title='abc',content='123')
author = User(username='jkc',password='123456')
# 要先儲存到資料庫中
author.save()
article.author = author
article.save()
並且以後如果想要獲取某個種類下所有的文章,可以通過article_set
來實現。示例程式碼如下:
user = User.objects.first()
# 獲取第一個使用者寫的所有文章
articles = user.article_set.all()
for article in articles:
print(article)
一對一
- 在Django中一對一是通過
models.OnetToOneField
來實現的。這個OneToOneField
其實本質上就是一個外來鍵,只不過這個外來鍵有一個唯一約束(unique key)
,來實現一對一。 - 以後如果想要反向引用,那麼是通過引用的模型的名字轉換為小寫的形式進行訪問。比如以下模型:
class FrontUser(models.Model):
username = models.CharField(max_length=200)
class UserExtension(models.Model):
school = models.CharField(max_length=100)
user = models.OneToOneField("FrontUser",on_delete=models.CASCADE)
# 通過userextension來訪問UserExtension物件
user = FrontUser.objects.first()
print(user.userextension)
UserExtension
的物件,可以通過user來訪問到對應的user物件。並且FrontUser
物件可以使用userextension
來訪問對應的UserExtension
物件。 如果不想使用Django預設的引用屬性名字。那麼可以在OneToOneField
中新增一個related_name
引數。示例程式碼如下:
class FrontUser(models.Model):
username = models.CharField(max_length=200)
class UserExtension(models.Model):
school = models.CharField(max_length=100)
user = models.OneToOneField("FrontUser",on_delete=models.CASCADE,related_name='extension')
# 通過extension來訪問到UserExtension物件
user = FrontUser.objects.first()
print(user.extension)
那麼以後就FrontUser
的物件就可以通過extension
屬性來訪問到對應的UserExtension
物件。
多對多
- 應用場景:比如文章和標籤的關係。一篇文章可以有多個標籤,一個標籤可以被多個文章所引用。因此標籤和文章的關係是典型的多對多的關係。
- 實現方式:Django為這種多對多的實現提供了專門的Field。叫做
ManyToManyField
。還是拿文章和標籤為例進行講解。示例程式碼如下:
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
tags = models.ManyToManyField("Tag",related_name="articles")
class Tag(models.Model):
name = models.CharField(max_length=50)
在資料庫層面,實際上Django是為這種多對多的關係建立了一箇中間表。這個中間表分別定義了兩個外來鍵,引用到article
和tag
兩張表的主鍵。
在我們使用多對多反向引用新增的時候,只能使用add
這種新增方式,比如向文章中新增標籤,示例程式碼如下:
article = Article.objects.first()
tag = Tag(name="好看")
tag.save()
article.tag_set.add(tag) # 向文章中新增標籤tag