1. 程式人生 > >如何理解數據庫多個表之間的聯系

如何理解數據庫多個表之間的聯系

title key 聯系 sch 兩個 並且 cat 主鍵 mode

## 一對多:

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`兩張表的主鍵。

如何理解數據庫多個表之間的聯系