## 一對多:
1. 應用場景:比如文章和作者之間的關系。一個文章只能由一個作者編寫,但是一個作者可以寫多篇文章。文章和作者之間的關系就是典型的多對一的關系。
2. 實現方式:一對多或者多對一,都是通過`ForeignKey`來實現的。還是以文章和作者的案例進行講解。
```python
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`對象指定`author`,就可以使用以下代碼來完成:
```python
article = Article(title='abc',content='123')
author = User(username='zhiliao',password='111111')
# 要先保存到數據庫中
author.save()
article.author = author
article.save()
```
並且以后如果想要獲取某個用戶下所有的文章,可以通過`article_set`來實現。示例代碼如下:
```python
user = User.objects.first()
# 獲取第一個用戶寫的所有文章
articles = user.article_set.all()
for article in articles:
print(article)
```
並且如果想要將文章添加到某個分類中。可以使用一下的方式:
```python
category = Category.objects.first()
article = Article(title='bbb',content='vvv')
article.author = FrontUser.objects.first()
category.article_set.add(article,bulk=False)
```
* 使用`bulk=False`,那么Django會自動的保存article,而不需要在添加到category之前先保存article。
* 或者是另外一種解決方式是,在添加到`category.article_set`中之前,先將`article`保存到數據庫中。但是如果`article.category`不能為空,那么就產生一種死循環了,article沒有`category`不能保存,而將article添加到`cateogry.artile_set`中,又需要article之前是已經存儲到數據庫中的。
* 如果是上面的那種需求,建議使用`bulk=False`的解決方案。
## 一對一:
1. 在Django中一對一是通過`models.OnetToOneField`來實現的。這個`OneToOneField`其實本質上就是一個外鍵,只不過這個外鍵有一個`唯一約束(unique key)`,來實現一對一。
2. 以后如果想要反向引用,那么是通過引用的模型的名字轉換為小寫的形式進行訪問。比如以下模型:
```python
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`參數。示例代碼如下:
```python
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`對象。
## 多對多:
1. 應用場景:比如文章和標簽的關系。一篇文章可以有多個標簽,一個標簽可以被多個文章所引用。因此標簽和文章的關系是典型的多對多的關系。
2. 實現方式:`Django`為這種多對多的實現提供了專門的`Field`。叫做`ManyToManyField`。還是拿文章和標簽為例進行講解。示例代碼如下:
```python
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`兩張表的主鍵。