Django 中的模型

已完成

模型是所有 ORM 的核心。 模型代表應用程式所要使用的一些資料。 這些資料可以是應用程式所需的人員、產品、類別,或是任何其他形式的資料。

建立模型

在 Django 中,所有從 django.models.Model 繼承功能集合的類別,都稱為模型。 此集合包含各種方法,可讓您查詢資料庫、建立新項目,以及儲存更新。 您也可以定義欄位、設定中繼資料,以及建立模型之間的關聯性。

您若想要建立兩個模型 (ProductCategory),必須新增兩個類別:

from django.db import models
class Product(models.Model):
    # details would go here
    pass

class Category(models.Model):
    # details would go here
    pass

新增方法

在討論如何設定模型的資料之前,必須先強調模型屬於 Python 類別。 因此,您可以同時新增方法及覆寫 Django.models.Model 所提供的方法,或所有 Python 物件固有的方法。

有一個需要特別強調的方法是 __str__。 當未指定任何欄位時,您可以使用此方法來顯示物件。 若 Product 有一個 name 欄位 (等下就會看到),您可以藉由覆寫 __str__,以 Product 的預設字串表示法傳回該欄位。

class Product(models.Model):
    name = models.TextField()
    
    def __str__(self):
        return self.name

新增欄位

欄位定義了模型的資料結構。 欄位可能包含項目的名稱、建立日期、價格,或其他任何模型需要儲存的資料片段。

不同的資料片段具有不同的資料類型、驗證規則及其他格式的中繼資料。 Django ORM 提供一組豐富的選項,可讓您依照自己的指定來設定模型的欄位。 ORM 可以擴充,因此您可以視需要建立自己的規則。

定義欄位類型

所有欄位的核心中繼資料,都是需要儲存的資料類型,例如字串或數字。 欄位類型會同時對應至資料庫類型與 HTML 表單控制項類型 (例如文字方塊或核取方塊)。 Django 包含幾種欄位類型 \(英文\),包括:

  • CharField:單行文字。
  • TextField:多行文字。
  • BooleanField:布林值 true/false 選項。
  • DateField:日期。
  • TimeField:時間。
  • DateTimeField:日期與時間。
  • URLField:URL。
  • IntegerField:整數。
  • DecimalField:固定有效位數的十進位數。

若要將欄位新增至我們的 ProductCategory 類別,我們的程式碼將會如下所示:

from django.db import models
class Product(models.Model):
    name = models.TextField()
    price = models.DecimalField()
    creation_date = models.DateField()

class Category(models.Model):
    name = models.TextField()

欄位選項

您可以使用欄位選項 \(英文\),新增中繼資料來允許 null 或空白值,或將欄位標示為不得重複。 您也可以設定驗證選項,以及為驗證錯誤提供自訂訊息。

一如欄位類型,欄位選項會對應到資料庫中適當的設定。 這些規則會在 Django 代您產生的所有表單中施行。

欄位選項會傳遞給欄位本身的函式。 不同的欄位可能支援不同的選項。 一些最常見的選項包括:

  • null
    • 允許 null 值的布林值選項。
    • 預設值為 False
  • blank
    • 允許空白值的布林值選項。
    • 預設值為 False
  • default
    • 若未提供欄位的值,將會允許設定預設值。
    • 若要將預設值設定為資料庫 null,請將 default 設定為 None
  • unique
    • 此欄位的值不得重複。
    • 預設值為 False
  • min_lengthmax_length
    • 搭配字串類型使用,可識別字串的最短與最長長度。
    • 預設值為 None
  • min_valuemax_value
    • 搭配數字類型使用,可識別最小值與最大值。
  • auto_nowauto_now_add
    • 搭配日期/時間類型使用,可指定是否應使用目前的時間。
    • auto_now「一律」會將欄位設定為儲存當時的時間,這對 last_update 欄位而言很有幫助。
    • auto_now_add 會將欄位設定為建立當時的時間,這對 creation_date 欄位而言很有幫助。

注意

儘管值 nullblank 看起來很相似,但在資料庫字詞中卻是表示不同的事物。 null 表示缺少值,blank 特別指空白值。

若要在模型中新增選項,程式碼可能如下所示:

from django.db import models
class Product(models.Model):
    name = models.TextField(max_length=50, min_length=3, unique=True)
    price = models.DecimalField(min_value=0.99, max_value=1000)
    creation_date = models.DateField(auto_now_add=True)

class Category(models.Model):
    name = models.TextField(max_length=50, min_length=3, unique=True)

索引鍵與關聯性

關聯式資料庫中的標準做法,是為資料表中的每個資料列設定主索引鍵,而這通常是自動遞增的整數。 Django 的 ORM 會藉由新增名為 id 的欄位,自動將此索引鍵新增至您建立的每個模型。

若您想要覆寫此行為,可以將您想要的欄位設定為您的主索引鍵。 在大部分情況下,您應該使用 Django 的 id 欄位。

關聯式資料庫的資料表之間也有關聯性。 產品有類別,員工有經理,汽車有製造商。 Django 的 ORM 可以支援您想要在模型之間建立的各種關聯性。

「一對多」是最常見的關聯性,技術名詞稱為「外部索引鍵關聯性」。 在外部索引鍵關聯性中,多個項目會共用同一個屬性。 例如將多項產品分組成同一類別。 若要建構此關聯性,必須使用 ForeignKey 欄位。

若要建立關聯性,必須將 ForeignKey 欄位新增至子物件。 若您將產品分為不同類別,可以將 category 屬性新增至 Product 類別,並將類型設定為 ForeignKey

Django 會自動將屬性新增至父系,以提供所有稱為 <child>_set 之子系的存取權,其中 <child> 是子物件的名稱。 在我們的範例中,Category 會自動新增 product_set,以提供類別中所有產品的存取權。

ForeignKey 有一個必要參數:on_delete \(英文\)。 此參數會告訴 Django 當父系刪除時所應採取的動作。 意即,若我們刪除了類別,該類別中的產品應如何?

最常見的兩個選項如下:

  • CASCADE:若我們的範例中有類別刪除,將會刪除所有產品。
  • PROTECT:若我們嘗試刪除內含產品的類別,將會傳回錯誤。

注意

在大多數情況下,您會想要使用 PROTECT

若要更新我們的模型來建立關聯性,可以使用下列程式碼:

from django.db import models
class Product(models.Model):
    name = models.TextField()
    price = models.DecimalField()
    creation_date = models.DateField()
    category = models.ForeignKey(
        'Category', #The name of the model
        on_delete=models.PROTECT
    )

class Category(models.Model):
    name = models.TextField()
    # product_set will be automatically created