Django中ORM介紹和欄位及欄位參數

  • 2020 年 3 月 17 日
  • 筆記

Object Relational Mapping(ORM)

ORM介紹

ORM概念

對象關係映射(Object Relational Mapping,簡稱ORM)模式是一種為了解決面向對象與關係資料庫存在的互不匹配的現象的技術。

簡單的說,ORM是通過使用描述對象和資料庫之間映射的元數據,將程式中的對象自動持久化到關係資料庫中。

ORM在業務邏輯層和資料庫層之間充當了橋樑的作用。

ORM由來

讓我們從O/R開始。字母O起源於”對象”(Object),而R則來自於”關係”(Relational)。

幾乎所有的軟體開發過程中都會涉及到對象和關係資料庫。在用戶層面和業務邏輯層面,我們是面向對象的。當對象的資訊發生變化的時候,我們就需要把對象的資訊保存在關係資料庫中。

按照之前的方式來進行開發就會出現程式設計師會在自己的業務邏輯程式碼中夾雜很多SQL語句用來增加、讀取、修改、刪除相關數據,而這些程式碼通常都是重複的。

ORM的優勢

ORM解決的主要問題是對象和關係的映射。它通常把一個類和一個表一一對應,類的每個實例對應表中的一條記錄,類的每個屬性對應表中的每個欄位。 

ORM提供了對資料庫的映射,不用直接編寫SQL程式碼,只需像操作對象一樣從資料庫操作數據。

讓軟體開發人員專註於業務邏輯的處理,提高了開發效率。

ORM的劣勢

ORM的缺點是會在一定程度上犧牲程式的執行效率。

ORM用多了SQL語句就不會寫了,關係資料庫相關技能退化…

ORM總結

ORM只是一種工具,工具確實能解決一些重複,簡單的勞動。這是不可否認的。

但我們不能指望某個工具能一勞永逸地解決所有問題,一些特殊問題還是需要特殊處理的。

但是在整個軟體開發過程中需要特殊處理的情況應該都是很少的,否則所謂的工具也就失去了它存在的意義。

Django中的ORM

Django項目使用MySQL資料庫

1. 在Django項目的settings.py文件中,配置資料庫連接資訊:

複製程式碼
DATABASES = {      "default": {          "ENGINE": "django.db.backends.mysql",          "NAME": "你的資料庫名稱",  # 需要自己手動創建資料庫          "USER": "資料庫用戶名",          "PASSWORD": "資料庫密碼",          "HOST": "資料庫IP",          "POST": 3306      }  }
複製程式碼

2. 在Django項目的__init__.py文件中寫如下程式碼,告訴Django使用pymysql模組連接MySQL資料庫:

import pymysql    pymysql.install_as_MySQLdb()

Model

在Django中model是你數據的單一、明確的資訊來源。它包含了你存儲的數據的重要欄位和行為。通常,一個模型(model)映射到一個資料庫表,

基本情況:

  • 每個模型都是一個Python類,它是django.db.models.Model的子類。
  • 模型的每個屬性都代表一個資料庫欄位。
  • 綜上所述,Django為您提供了一個自動生成的資料庫訪問API,詳詢官方文檔鏈接

 

快速入門 

下面這個例子定義了一個 Person 模型,包含 first_name 和 last_name

from django.db import models    class Person(models.Model):      first_name = models.CharField(max_length=30)      last_name = models.CharField(max_length=30)

first_name 和 last_name 是模型的欄位。每個欄位被指定為一個類屬性,每個屬性映射到一個資料庫列。

上面的 Person 模型將會像這樣創建一個資料庫表:

CREATE TABLE myapp_person (      "id" serial NOT NULL PRIMARY KEY,      "first_name" varchar(30) NOT NULL,      "last_name" varchar(30) NOT NULL  );

一些說明:

  • 表myapp_person的名稱是自動生成的,如果你要自定義表名,需要在model的Meta類中指定 db_table 參數,強烈建議使用小寫表名,特別是使用MySQL作為後端資料庫時。
  • id欄位是自動添加的,如果你想要指定自定義主鍵,只需在其中一個欄位中指定 primary_key=True 即可。如果Django發現你已經明確地設置了Field.primary_key,它將不會添加自動ID列。
  • 本示例中的CREATE TABLE SQL使用PostgreSQL語法進行格式化,但值得注意的是,Django會根據配置文件中指定的資料庫後端類型來生成相應的SQL語句。
  • Django支援MySQL5.5及更高版本。

Django ORM 常用欄位和參數

常用欄位

AutoField

int自增列,必須填入參數 primary_key=True。當model中如果沒有自增列,則自動會創建一個列名為id的列。

IntegerField

一個整數類型,範圍在 -2147483648 to 2147483647。

CharField

字元類型,必須提供max_length參數, max_length表示字元長度。

DateField

日期欄位,日期格式  YYYY-MM-DD,相當於Python中的datetime.date()實例。

DateTimeField

日期時間欄位,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相當於Python中的datetime.datetime()實例。

欄位合集(爭取記憶)

複製程式碼
   AutoField(Field)          - int自增列,必須填入參數 primary_key=True        BigAutoField(AutoField)          - bigint自增列,必須填入參數 primary_key=True            註:當model中如果沒有自增列,則自動會創建一個列名為id的列          from django.db import models            class UserInfo(models.Model):              # 自動創建一個列名為id的且為自增的整數列              username = models.CharField(max_length=32)            class Group(models.Model):              # 自定義自增列              nid = models.AutoField(primary_key=True)              name = models.CharField(max_length=32)        SmallIntegerField(IntegerField):          - 小整數 -32768 ~ 32767        PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)          - 正小整數 0 ~ 32767      IntegerField(Field)          - 整數列(有符號的) -2147483648 ~ 2147483647        PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)          - 正整數 0 ~ 2147483647        BigIntegerField(IntegerField):          - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807        BooleanField(Field)          - 布爾值類型        NullBooleanField(Field):          - 可以為空的布爾值        CharField(Field)          - 字元類型          - 必須提供max_length參數, max_length表示字元長度        TextField(Field)          - 文本類型        EmailField(CharField):          - 字元串類型,Django Admin以及ModelForm中提供驗證機制        IPAddressField(Field)          - 字元串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制        GenericIPAddressField(Field)          - 字元串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6          - 參數:              protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"              unpack_ipv4, 如果指定為True,則輸入::ffff:192.0.2.1時候,可解析為192.0.2.1,開啟此功能,需要protocol="both"        URLField(CharField)          - 字元串類型,Django Admin以及ModelForm中提供驗證 URL        SlugField(CharField)          - 字元串類型,Django Admin以及ModelForm中提供驗證支援 字母、數字、下劃線、連接符(減號)        CommaSeparatedIntegerField(CharField)          - 字元串類型,格式必須為逗號分割的數字        UUIDField(Field)          - 字元串類型,Django Admin以及ModelForm中提供對UUID格式的驗證        FilePathField(Field)          - 字元串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能          - 參數:                  path,                      文件夾路徑                  match=None,                正則匹配                  recursive=False,           遞歸下面的文件夾                  allow_files=True,          允許文件                  allow_folders=False,       允許文件夾        FileField(Field)          - 字元串,路徑保存在資料庫,文件上傳到指定目錄          - 參數:              upload_to = ""      上傳文件的保存路徑              storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage        ImageField(FileField)          - 字元串,路徑保存在資料庫,文件上傳到指定目錄          - 參數:              upload_to = ""      上傳文件的保存路徑              storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage              width_field=None,   上傳圖片的高度保存的資料庫欄位名(字元串)              height_field=None   上傳圖片的寬度保存的資料庫欄位名(字元串)        DateTimeField(DateField)          - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]        DateField(DateTimeCheckMixin, Field)          - 日期格式      YYYY-MM-DD        TimeField(DateTimeCheckMixin, Field)          - 時間格式      HH:MM[:ss[.uuuuuu]]        DurationField(Field)          - 長整數,時間間隔,資料庫中按照bigint存儲,ORM中獲取的值為datetime.timedelta類型        FloatField(Field)          - 浮點型        DecimalField(Field)          - 10進位小數          - 參數:              max_digits,小數總長度              decimal_places,小數位長度        BinaryField(Field)          - 二進位類型
複製程式碼

自定義欄位(了解為主)

class UnsignedIntegerField(models.IntegerField):      def db_type(self, connection):          return 'integer UNSIGNED'

自定義char類型欄位:

複製程式碼
class FixedCharField(models.Field):      """      自定義的char類型的欄位類      """      def __init__(self, max_length, *args, **kwargs):          super().__init__(max_length=max_length, *args, **kwargs)          self.length = max_length        def db_type(self, connection):          """          限定生成資料庫表的欄位類型為char,長度為length指定的值          """          return 'char(%s)' % self.length      class Class(models.Model):      id = models.AutoField(primary_key=True)      title = models.CharField(max_length=25)      # 使用上面自定義的char類型的欄位      cname = FixedCharField(max_length=25)
複製程式碼

創建的表結構:

附ORM欄位與資料庫實際欄位的對應關係

對應關係

欄位參數

null

用於表示某個欄位可以為空。

unique

如果設置為unique=True 則該欄位在此表中必須是唯一的 。

db_index

如果db_index=True 則代表著為此欄位設置資料庫索引。

default

為該欄位設置默認值。

時間欄位獨有

DatetimeField、DateField、TimeField這個三個時間欄位,都可以設置如下屬性。

auto_now_add

配置auto_now_add=True,創建數據記錄的時候會把當前時間添加到資料庫。

auto_now

配置上auto_now=True,每次更新數據記錄的時候會更新該欄位。

 

關係欄位

ForeignKey

外鍵類型在ORM中用來表示外鍵關聯關係,一般把ForeignKey欄位設置在 ‘一對多’中’多’的一方。

ForeignKey可以和其他表做關聯關係同時也可以和自身做關聯關係。

欄位參數

to

設置要關聯的表

to_field

設置要關聯的表的欄位

related_name

反向操作時,使用的欄位名,用於代替原反向查詢時的’表名_set’。

例如:

複製程式碼
class Classes(models.Model):      name = models.CharField(max_length=32)    class Student(models.Model):      name = models.CharField(max_length=32)      theclass = models.ForeignKey(to="Classes")
複製程式碼

當我們要查詢某個班級關聯的所有學生(反向查詢)時,我們會這麼寫:

models.Classes.objects.first().student_set.all()

當我們在ForeignKey欄位中添加了參數 related_name 後,

class Student(models.Model):      name = models.CharField(max_length=32)      theclass = models.ForeignKey(to="Classes", related_name="students")

當我們要查詢某個班級關聯的所有學生(反向查詢)時,我們會這麼寫:

models.Classes.objects.first().students.all()

related_query_name

反向查詢操作時,使用的連接前綴,用於替換表名。

on_delete

當刪除關聯表中的數據時,當前表與其關聯的行的行為。

models.CASCADE
刪除關聯數據,與之關聯也刪除

models.DO_NOTHING
刪除關聯數據,引發錯誤IntegrityError

models.PROTECT
刪除關聯數據,引發錯誤ProtectedError

models.SET_NULL
刪除關聯數據,與之關聯的值設置為null(前提FK欄位需要設置為可空)

models.SET_DEFAULT
刪除關聯數據,與之關聯的值設置為默認值(前提FK欄位需要設置默認值)

models.SET

刪除關聯數據,
a. 與之關聯的值設置為指定值,設置:models.SET(值)
b. 與之關聯的值設置為可執行對象的返回值,設置:models.SET(可執行對象)

複製程式碼
def func():      return 10    class MyModel(models.Model):      user = models.ForeignKey(          to="User",          to_field="id",          on_delete=models.SET(func)      )
複製程式碼

db_constraint

是否在資料庫中創建外鍵約束,默認為True。

OneToOneField

一對一欄位。

通常一對一欄位用來擴展已有欄位。

示例

一對一的關聯關係多用在當一張表的不同欄位查詢頻次差距過大的情況下,將本可以存儲在一張表的欄位拆開放置在兩張表中,然後將兩張表建立一對一的關聯關係。

複製程式碼
class Author(models.Model):      name = models.CharField(max_length=32)      info = models.OneToOneField(to='AuthorInfo')      class AuthorInfo(models.Model):      phone = models.CharField(max_length=11)      email = models.EmailField()

 

複製程式碼

欄位參數

to

設置要關聯的表。

to_field

設置要關聯的欄位。

on_delete

同ForeignKey欄位。

ManyToManyField

用於表示多對多的關聯關係。在資料庫中通過第三張表來建立關聯關係。

欄位參數

to

設置要關聯的表

related_name

同ForeignKey欄位。

related_query_name

同ForeignKey欄位。

symmetrical

僅用於多對多自關聯時,指定內部是否創建反向操作的欄位。默認為True。

舉個例子:

class Person(models.Model):      name = models.CharField(max_length=16)      friends = models.ManyToManyField("self")

此時,person對象就沒有person_set屬性。

class Person(models.Model):      name = models.CharField(max_length=16)      friends = models.ManyToManyField("self", symmetrical=False)

此時,person對象現在就可以使用person_set屬性進行反向查詢。

through

在使用ManyToManyField欄位時,Django將自動生成一張表來管理多對多的關聯關係。

但我們也可以手動創建第三張表來管理多對多關係,此時就需要通過through來指定第三張表的表名。

through_fields

設置關聯的欄位。

db_table

默認創建第三張表時,資料庫中表的名稱。

多對多關聯關係的三種方式 

方式一:自行創建第三張表

複製程式碼
class Book(models.Model):      title = models.CharField(max_length=32, verbose_name="書名")      class Author(models.Model):      name = models.CharField(max_length=32, verbose_name="作者姓名")      # 自己創建第三張表,分別通過外鍵關聯書和作者  class Author2Book(models.Model):      author = models.ForeignKey(to="Author")      book = models.ForeignKey(to="Book")        class Meta:          unique_together = ("author", "book")
複製程式碼

方式二:通過ManyToManyField自動創建第三張表

複製程式碼
class Book(models.Model):      title = models.CharField(max_length=32, verbose_name="書名")      # 通過ORM自帶的ManyToManyField自動創建第三張表  class Author(models.Model):      name = models.CharField(max_length=32, verbose_name="作者姓名")      books = models.ManyToManyField(to="Book", related_name="authors")
複製程式碼

方式三:設置ManyTomanyField並指定自行創建的第三張表

複製程式碼
class Book(models.Model):      title = models.CharField(max_length=32, verbose_name="書名")      # 自己創建第三張表,並通過ManyToManyField指定關聯  class Author(models.Model):      name = models.CharField(max_length=32, verbose_name="作者姓名")      books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))      # through_fields接受一個2元組('field1','field2'):      # 其中field1是定義ManyToManyField的模型外鍵的名(author),field2是關聯目標模型(book)的外鍵名。      class Author2Book(models.Model):      author = models.ForeignKey(to="Author")      book = models.ForeignKey(to="Book")        class Meta:          unique_together = ("author", "book")
複製程式碼

 

注意:

當我們需要在第三張關係表中存儲額外的欄位時,就要使用第三種方式。

但是當我們使用第三種方式創建多對多關聯關係時,就無法使用set、add、remove、clear方法來管理多對多的關係了,需要通過第三張表的model來管理多對多關係。

元資訊

ORM對應的類裡面包含另一個Meta類,而Meta類封裝了一些資料庫的資訊。主要欄位如下:

db_table

ORM在資料庫中的表名默認是 app_類名,可以通過db_table可以重寫表名。

index_together

聯合索引。

unique_together

聯合唯一索引。

ordering

指定默認按什麼欄位排序。

只有設置了該屬性,我們查詢到的結果才可以被reverse()。

 

Object Relational Mapping(ORM)

ORM介紹

ORM概念

對象關係映射(Object Relational Mapping,簡稱ORM)模式是一種為了解決面向對象與關係資料庫存在的互不匹配的現象的技術。

簡單的說,ORM是通過使用描述對象和資料庫之間映射的元數據,將程式中的對象自動持久化到關係資料庫中。

ORM在業務邏輯層和資料庫層之間充當了橋樑的作用。

ORM由來

讓我們從O/R開始。字母O起源於”對象”(Object),而R則來自於”關係”(Relational)。

幾乎所有的軟體開發過程中都會涉及到對象和關係資料庫。在用戶層面和業務邏輯層面,我們是面向對象的。當對象的資訊發生變化的時候,我們就需要把對象的資訊保存在關係資料庫中。

按照之前的方式來進行開發就會出現程式設計師會在自己的業務邏輯程式碼中夾雜很多SQL語句用來增加、讀取、修改、刪除相關數據,而這些程式碼通常都是重複的。

ORM的優勢

ORM解決的主要問題是對象和關係的映射。它通常把一個類和一個表一一對應,類的每個實例對應表中的一條記錄,類的每個屬性對應表中的每個欄位。 

ORM提供了對資料庫的映射,不用直接編寫SQL程式碼,只需像操作對象一樣從資料庫操作數據。

讓軟體開發人員專註於業務邏輯的處理,提高了開發效率。

ORM的劣勢

ORM的缺點是會在一定程度上犧牲程式的執行效率。

ORM用多了SQL語句就不會寫了,關係資料庫相關技能退化…

ORM總結

ORM只是一種工具,工具確實能解決一些重複,簡單的勞動。這是不可否認的。

但我們不能指望某個工具能一勞永逸地解決所有問題,一些特殊問題還是需要特殊處理的。

但是在整個軟體開發過程中需要特殊處理的情況應該都是很少的,否則所謂的工具也就失去了它存在的意義。

Django中的ORM

Django項目使用MySQL資料庫

1. 在Django項目的settings.py文件中,配置資料庫連接資訊:

複製程式碼
DATABASES = {      "default": {          "ENGINE": "django.db.backends.mysql",          "NAME": "你的資料庫名稱",  # 需要自己手動創建資料庫          "USER": "資料庫用戶名",          "PASSWORD": "資料庫密碼",          "HOST": "資料庫IP",          "POST": 3306      }  }
複製程式碼

2. 在Django項目的__init__.py文件中寫如下程式碼,告訴Django使用pymysql模組連接MySQL資料庫:

import pymysql    pymysql.install_as_MySQLdb()

Model

在Django中model是你數據的單一、明確的資訊來源。它包含了你存儲的數據的重要欄位和行為。通常,一個模型(model)映射到一個資料庫表,

基本情況:

  • 每個模型都是一個Python類,它是django.db.models.Model的子類。
  • 模型的每個屬性都代表一個資料庫欄位。
  • 綜上所述,Django為您提供了一個自動生成的資料庫訪問API,詳詢官方文檔鏈接

 

快速入門 

下面這個例子定義了一個 Person 模型,包含 first_name 和 last_name

from django.db import models    class Person(models.Model):      first_name = models.CharField(max_length=30)      last_name = models.CharField(max_length=30)

first_name 和 last_name 是模型的欄位。每個欄位被指定為一個類屬性,每個屬性映射到一個資料庫列。

上面的 Person 模型將會像這樣創建一個資料庫表:

CREATE TABLE myapp_person (      "id" serial NOT NULL PRIMARY KEY,      "first_name" varchar(30) NOT NULL,      "last_name" varchar(30) NOT NULL  );

一些說明:

  • 表myapp_person的名稱是自動生成的,如果你要自定義表名,需要在model的Meta類中指定 db_table 參數,強烈建議使用小寫表名,特別是使用MySQL作為後端資料庫時。
  • id欄位是自動添加的,如果你想要指定自定義主鍵,只需在其中一個欄位中指定 primary_key=True 即可。如果Django發現你已經明確地設置了Field.primary_key,它將不會添加自動ID列。
  • 本示例中的CREATE TABLE SQL使用PostgreSQL語法進行格式化,但值得注意的是,Django會根據配置文件中指定的資料庫後端類型來生成相應的SQL語句。
  • Django支援MySQL5.5及更高版本。

Django ORM 常用欄位和參數

常用欄位

AutoField

int自增列,必須填入參數 primary_key=True。當model中如果沒有自增列,則自動會創建一個列名為id的列。

IntegerField

一個整數類型,範圍在 -2147483648 to 2147483647。

CharField

字元類型,必須提供max_length參數, max_length表示字元長度。

DateField

日期欄位,日期格式  YYYY-MM-DD,相當於Python中的datetime.date()實例。

DateTimeField

日期時間欄位,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相當於Python中的datetime.datetime()實例。

欄位合集(爭取記憶)

複製程式碼
   AutoField(Field)          - int自增列,必須填入參數 primary_key=True        BigAutoField(AutoField)          - bigint自增列,必須填入參數 primary_key=True            註:當model中如果沒有自增列,則自動會創建一個列名為id的列          from django.db import models            class UserInfo(models.Model):              # 自動創建一個列名為id的且為自增的整數列              username = models.CharField(max_length=32)            class Group(models.Model):              # 自定義自增列              nid = models.AutoField(primary_key=True)              name = models.CharField(max_length=32)        SmallIntegerField(IntegerField):          - 小整數 -32768 ~ 32767        PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)          - 正小整數 0 ~ 32767      IntegerField(Field)          - 整數列(有符號的) -2147483648 ~ 2147483647        PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)          - 正整數 0 ~ 2147483647        BigIntegerField(IntegerField):          - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807        BooleanField(Field)          - 布爾值類型        NullBooleanField(Field):          - 可以為空的布爾值        CharField(Field)          - 字元類型          - 必須提供max_length參數, max_length表示字元長度        TextField(Field)          - 文本類型        EmailField(CharField):          - 字元串類型,Django Admin以及ModelForm中提供驗證機制        IPAddressField(Field)          - 字元串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制        GenericIPAddressField(Field)          - 字元串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6          - 參數:              protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"              unpack_ipv4, 如果指定為True,則輸入::ffff:192.0.2.1時候,可解析為192.0.2.1,開啟此功能,需要protocol="both"        URLField(CharField)          - 字元串類型,Django Admin以及ModelForm中提供驗證 URL        SlugField(CharField)          - 字元串類型,Django Admin以及ModelForm中提供驗證支援 字母、數字、下劃線、連接符(減號)        CommaSeparatedIntegerField(CharField)          - 字元串類型,格式必須為逗號分割的數字        UUIDField(Field)          - 字元串類型,Django Admin以及ModelForm中提供對UUID格式的驗證        FilePathField(Field)          - 字元串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能          - 參數:                  path,                      文件夾路徑                  match=None,                正則匹配                  recursive=False,           遞歸下面的文件夾                  allow_files=True,          允許文件                  allow_folders=False,       允許文件夾        FileField(Field)          - 字元串,路徑保存在資料庫,文件上傳到指定目錄          - 參數:              upload_to = ""      上傳文件的保存路徑              storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage        ImageField(FileField)          - 字元串,路徑保存在資料庫,文件上傳到指定目錄          - 參數:              upload_to = ""      上傳文件的保存路徑              storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage              width_field=None,   上傳圖片的高度保存的資料庫欄位名(字元串)              height_field=None   上傳圖片的寬度保存的資料庫欄位名(字元串)        DateTimeField(DateField)          - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]        DateField(DateTimeCheckMixin, Field)          - 日期格式      YYYY-MM-DD        TimeField(DateTimeCheckMixin, Field)          - 時間格式      HH:MM[:ss[.uuuuuu]]        DurationField(Field)          - 長整數,時間間隔,資料庫中按照bigint存儲,ORM中獲取的值為datetime.timedelta類型        FloatField(Field)          - 浮點型        DecimalField(Field)          - 10進位小數          - 參數:              max_digits,小數總長度              decimal_places,小數位長度        BinaryField(Field)          - 二進位類型
複製程式碼

自定義欄位(了解為主)

class UnsignedIntegerField(models.IntegerField):      def db_type(self, connection):          return 'integer UNSIGNED'

自定義char類型欄位:

複製程式碼
class FixedCharField(models.Field):      """      自定義的char類型的欄位類      """      def __init__(self, max_length, *args, **kwargs):          super().__init__(max_length=max_length, *args, **kwargs)          self.length = max_length        def db_type(self, connection):          """          限定生成資料庫表的欄位類型為char,長度為length指定的值          """          return 'char(%s)' % self.length      class Class(models.Model):      id = models.AutoField(primary_key=True)      title = models.CharField(max_length=25)      # 使用上面自定義的char類型的欄位      cname = FixedCharField(max_length=25)
複製程式碼

創建的表結構:

附ORM欄位與資料庫實際欄位的對應關係

對應關係

欄位參數

null

用於表示某個欄位可以為空。

unique

如果設置為unique=True 則該欄位在此表中必須是唯一的 。

db_index

如果db_index=True 則代表著為此欄位設置資料庫索引。

default

為該欄位設置默認值。

時間欄位獨有

DatetimeField、DateField、TimeField這個三個時間欄位,都可以設置如下屬性。

auto_now_add

配置auto_now_add=True,創建數據記錄的時候會把當前時間添加到資料庫。

auto_now

配置上auto_now=True,每次更新數據記錄的時候會更新該欄位。

 

關係欄位

ForeignKey

外鍵類型在ORM中用來表示外鍵關聯關係,一般把ForeignKey欄位設置在 ‘一對多’中’多’的一方。

ForeignKey可以和其他表做關聯關係同時也可以和自身做關聯關係。

欄位參數

to

設置要關聯的表

to_field

設置要關聯的表的欄位

related_name

反向操作時,使用的欄位名,用於代替原反向查詢時的’表名_set’。

例如:

複製程式碼
class Classes(models.Model):      name = models.CharField(max_length=32)    class Student(models.Model):      name = models.CharField(max_length=32)      theclass = models.ForeignKey(to="Classes")
複製程式碼

當我們要查詢某個班級關聯的所有學生(反向查詢)時,我們會這麼寫:

models.Classes.objects.first().student_set.all()

當我們在ForeignKey欄位中添加了參數 related_name 後,

class Student(models.Model):      name = models.CharField(max_length=32)      theclass = models.ForeignKey(to="Classes", related_name="students")

當我們要查詢某個班級關聯的所有學生(反向查詢)時,我們會這麼寫:

models.Classes.objects.first().students.all()

related_query_name

反向查詢操作時,使用的連接前綴,用於替換表名。

on_delete

當刪除關聯表中的數據時,當前表與其關聯的行的行為。

models.CASCADE
刪除關聯數據,與之關聯也刪除

models.DO_NOTHING
刪除關聯數據,引發錯誤IntegrityError

models.PROTECT
刪除關聯數據,引發錯誤ProtectedError

models.SET_NULL
刪除關聯數據,與之關聯的值設置為null(前提FK欄位需要設置為可空)

models.SET_DEFAULT
刪除關聯數據,與之關聯的值設置為默認值(前提FK欄位需要設置默認值)

models.SET

刪除關聯數據,
a. 與之關聯的值設置為指定值,設置:models.SET(值)
b. 與之關聯的值設置為可執行對象的返回值,設置:models.SET(可執行對象)

複製程式碼
def func():      return 10    class MyModel(models.Model):      user = models.ForeignKey(          to="User",          to_field="id",          on_delete=models.SET(func)      )
複製程式碼

db_constraint

是否在資料庫中創建外鍵約束,默認為True。

OneToOneField

一對一欄位。

通常一對一欄位用來擴展已有欄位。

示例

一對一的關聯關係多用在當一張表的不同欄位查詢頻次差距過大的情況下,將本可以存儲在一張表的欄位拆開放置在兩張表中,然後將兩張表建立一對一的關聯關係。

複製程式碼
class Author(models.Model):      name = models.CharField(max_length=32)      info = models.OneToOneField(to='AuthorInfo')      class AuthorInfo(models.Model):      phone = models.CharField(max_length=11)      email = models.EmailField()

 

複製程式碼

欄位參數

to

設置要關聯的表。

to_field

設置要關聯的欄位。

on_delete

同ForeignKey欄位。

ManyToManyField

用於表示多對多的關聯關係。在資料庫中通過第三張表來建立關聯關係。

欄位參數

to

設置要關聯的表

related_name

同ForeignKey欄位。

related_query_name

同ForeignKey欄位。

symmetrical

僅用於多對多自關聯時,指定內部是否創建反向操作的欄位。默認為True。

舉個例子:

class Person(models.Model):      name = models.CharField(max_length=16)      friends = models.ManyToManyField("self")

此時,person對象就沒有person_set屬性。

class Person(models.Model):      name = models.CharField(max_length=16)      friends = models.ManyToManyField("self", symmetrical=False)

此時,person對象現在就可以使用person_set屬性進行反向查詢。

through

在使用ManyToManyField欄位時,Django將自動生成一張表來管理多對多的關聯關係。

但我們也可以手動創建第三張表來管理多對多關係,此時就需要通過through來指定第三張表的表名。

through_fields

設置關聯的欄位。

db_table

默認創建第三張表時,資料庫中表的名稱。

多對多關聯關係的三種方式 

方式一:自行創建第三張表

複製程式碼
class Book(models.Model):      title = models.CharField(max_length=32, verbose_name="書名")      class Author(models.Model):      name = models.CharField(max_length=32, verbose_name="作者姓名")      # 自己創建第三張表,分別通過外鍵關聯書和作者  class Author2Book(models.Model):      author = models.ForeignKey(to="Author")      book = models.ForeignKey(to="Book")        class Meta:          unique_together = ("author", "book")
複製程式碼

方式二:通過ManyToManyField自動創建第三張表

複製程式碼
class Book(models.Model):      title = models.CharField(max_length=32, verbose_name="書名")      # 通過ORM自帶的ManyToManyField自動創建第三張表  class Author(models.Model):      name = models.CharField(max_length=32, verbose_name="作者姓名")      books = models.ManyToManyField(to="Book", related_name="authors")
複製程式碼

方式三:設置ManyTomanyField並指定自行創建的第三張表

複製程式碼
class Book(models.Model):      title = models.CharField(max_length=32, verbose_name="書名")      # 自己創建第三張表,並通過ManyToManyField指定關聯  class Author(models.Model):      name = models.CharField(max_length=32, verbose_name="作者姓名")      books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))      # through_fields接受一個2元組('field1','field2'):      # 其中field1是定義ManyToManyField的模型外鍵的名(author),field2是關聯目標模型(book)的外鍵名。      class Author2Book(models.Model):      author = models.ForeignKey(to="Author")      book = models.ForeignKey(to="Book")        class Meta:          unique_together = ("author", "book")
複製程式碼

 

注意:

當我們需要在第三張關係表中存儲額外的欄位時,就要使用第三種方式。

但是當我們使用第三種方式創建多對多關聯關係時,就無法使用set、add、remove、clear方法來管理多對多的關係了,需要通過第三張表的model來管理多對多關係。

元資訊

ORM對應的類裡面包含另一個Meta類,而Meta類封裝了一些資料庫的資訊。主要欄位如下:

db_table

ORM在資料庫中的表名默認是 app_類名,可以通過db_table可以重寫表名。

index_together

聯合索引。

unique_together

聯合唯一索引。

ordering

指定默認按什麼欄位排序。

只有設置了該屬性,我們查詢到的結果才可以被reverse()。