外鍵刪除操作
如果一個模型使用了外鍵。那么在對方那個模型被刪掉后,該進行什么樣的操作。可以通過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