1. 程式人生 > >Django模型(欄位、資料庫操作及模型繼承)

Django模型(欄位、資料庫操作及模型繼承)

Django資料庫欄位型別(Field types)

AutoField

class AutoField(**options)

BooleanField

class BooleanField(**options)

一個布林值(true/false)欄位。Django 的管理後臺用checkbox來表現該欄位型別。

MySQL 使用者請注意:

布林欄位在 MySQL 中被儲存為 TINYINT 列。它的值只能是 0 或 1 (其他大多資料庫都有適用的 BOOLEAN 型別)。所以僅在使用 MySQL 的情況下,從資料庫中檢索 BooleanField 並儲存為 model 的屬性,這時屬性值是 1 或是 0 ,而不是 True

 或 False 。正常情況下,這不會引起問題,因為 Python 保證令 1 == True 和 0 == False 都是有效的。只是在你編寫類似 obj isTrue 語句時,如果 obj 正是 model 的一個布林屬性值,那你就要留心注意了。因為在使用 mysql 資料庫時,"is" 操作是無效的。在這種場合下,使用相等判斷更好(使用 "==")。

CharField

class CharField(max_length=None[**options])
它是一個字串欄位,對小字串和大字串都適用。對於更大的文字,應該使用 TextField 。

Django 的管理後臺用 <input

 type="text"> (單行輸入框) 來表示這種欄位。

CharField 有一個必須傳入的引數,欄位的最大字元數。它作用於資料庫層級和 Django 的資料驗證層級。

注意:如果你正在編寫的應用要求滿足多種資料庫,那麼你就要注意不同資料庫對 max_length 有不同的限制。詳見 資料庫 (database backend notes) 。

MySQL 使用者請注意:

如果你使用 MySQLdb 1.2.2 和 utf8_bin 字符集(非預設設定),有幾點注意事項要格外留意。詳見 MySQL 資料庫 (MySQL database notes) 。

CommaSeparatedIntegerField

class CommaSeparatedIntegerField(max_length=None[**options])

它用來存放以逗號間隔的整數序列。和 CharField 一樣,必須為它提供 max_length 引數。而且要注意不同資料庫對 max_length 的限制。

時間欄位

DateTimeField和DateField和TimeField儲存的內容分別對應著datetime(),date(),time()三個物件。
auto_now=Ture,欄位儲存時會自動儲存當前時間,但要注意每次對其例項執行save()的時候都會將當前時間儲存,也就是不能再手動給它存非當前時間的值。
auto_now_add=True,欄位在例項第一次儲存的時候會儲存當前時間,不管你在這裡是否對其賦值。但是之後的save()是可以手動賦值的。也就是新例項化一個model,想手動存其他時間,就需要對該例項save()之後賦值然後再save()。

Note:兩者預設值都為False。

Django自動添加當前日期時間到資料庫

models.DateTimeField(auto_now_add=True)
DateField
class DateField([auto_now=Falseauto_now_add=False**options])

該欄位利用 Python 的 datetime.date 例項來表示日期。下面是它額外的可選引數:

DateField.auto_now
每一次儲存物件時,Django 都會自動將該欄位的值設定為當前時間。一般用來表示 "最後修改" 時間。要注意使用的是當前日期,而並非預設值,所以你不能通過重寫預設值的辦法來改變儲存時間。
DateField.auto_now_add
在第一次建立物件時,Django 自動將該欄位的值設定為當前時間,一般用來表示物件建立時間。它使用的同樣是當前日期,而非預設值。

Django 管理後臺使用一個帶有 Javascript 日曆的 <input type="text"> 來表示該欄位,它帶有一個當前日期的快捷選擇。那個 JavaScript 日曆總是以星期天做為一個星期的第一天。

DateTimeField

class DateTimeField([auto_now=Falseauto_now_add=False**options])

該欄位利用 datetime.datetime 例項表示日期和時間。該欄位所按受的引數和 DateField 一樣。

Django 的管理後臺使用兩個 <input type="text"> 分別表示日期和時間,同樣也帶有 JavaScript 快捷選項。

TimeField

class TimeField([auto_now=Falseauto_now_add=False**options])

該欄位使用 Python 的 datetime.time 例項來表示時間。它和 DateField 接受同樣的自動填充的引數。Django 管理後臺使用一個帶 Javascript 快捷連結 的 <input type="text"> 表示該欄位。

DurationField

New in Django 1.8.

DecimalField

這部分是在 Django 1.0 中新增的: 請檢視版本文件
class DecimalField(max_digits=Nonedecimal_places=None[**options])

它是使用 Decimal 例項表示固定精度的十進位制數的欄位。它有兩個必須的引數:

DecimalField.max_digits
數字允許的最大位數
DecimalField.decimal_places
小數的最大位數

例如,要儲存的數字最大值是999,而帶有兩個小數位,你可以使用:

models.DecimalField(..., max_digits=5, decimal_places=2)

要儲存大約是十億級且帶有10個小數位的數字,就這樣寫:

models.DecimalField(..., max_digits=19, decimal_places=10)

Django 管理後臺使用 <input type="text"> (單行輸入框) 表示該欄位。

EmailField

class EmailField([max_length=75**options]),它是帶有 email 合法性檢測的A CharField 。

FileField

class FileField(upload_to=None[max_length=100**options])

檔案上傳欄位

注意:該欄位不支援 primary_key 和 unique 引數,否則會丟擲 TypeError 異常。

它有一個必須的引數:FileField.upload_to

用於儲存檔案的本地檔案系統。它根據 MEDIA_ROOT 設定確定該檔案的 url 屬性。

該路徑可以包含 時間格式串 (strftime formatting),可以在上傳檔案的時候替換成當時日期/時間(這樣,就不會出現在上傳檔案把某個目錄塞滿的情況了)。

在 Django 1.0 已改動: 請檢視版本文件

該引數也可以是一個可呼叫項,比如是一個函式,可以呼叫函式獲得包含檔名的上傳路徑。這個可呼叫項必須要接受兩個引數,並且返回一個儲存檔案用的 Unix-Style 的路徑(用 / 斜槓)。兩個引數分別是:

引數 描述
instance

定義了當前 FileField 的 model 例項。更準確地說,就是以該檔案為附件的 model 例項。

大多數情況下,在儲存該檔案時, model 例項物件還並沒有儲存到資料庫,這是因為它很有可能使用預設的 AutoField,而此時它還沒有從資料庫中獲得主鍵值。(用法見oteam的http://oteam.cn/2008/10/4/dynamic-upload-paths-in-django/)

filename 上傳檔案的原始名稱。在生成最終路徑的時候,有可能會用到它。

還有一個可選的引數:

FileField.storage
這部分是在 Django 1.0 中新增的: 請檢視版本文件

Django 管理後臺使用 <input type="file"> (一個檔案上傳的部件) 來表示這個物件。

在 model 中使用 FileField 或 ImageField (稍後提到) 要按照以下的步驟:

  1. 在專案配置檔案中,你要定義 MEDIA_ROOT ,將它的值設為用來存放上傳檔案的目錄的完整路徑。(基於效能的考慮,Django 沒有將檔案儲存在資料庫中。) ,然後定義 MEDIA_URL ,將它的值設為表示該目錄的網址。要確保 web 伺服器所用的帳號擁有對該目錄的寫許可權。
  2. 儲存在資料庫當中的僅僅只是檔案的路徑(而且是相對於 MEDIA_ROOT 的相對路徑)。你可能已經想到利用 Django 提供的 url 這個方便的函式。舉個例子,如果你的 ImageField 名稱是mug_shot,那麼你可以在模板中使用 {{ object.mug_shot.url }} ,就能得到圖片的完整網址。

例如,假設你的 MEDIA_ROOT 被設為 '/home/media'upload_to 被設為 'photos/%Y/%m/%d'。 upload_to 中的 '%Y/%m/%d' 是一個 時間格式字串 (strftime formatting); '%Y' 是四位的年分,'%m' 是兩位的月分, '%d' 是兩位的日子。如果你在2007年01月15號上傳了一個檔案,那麼這個檔案就儲存在 /home/media/photos/2007/01/15 目錄下。

如果你想得到上傳檔案的本地檔名稱,檔案網址,或是檔案的大小,你可以使用 nameurl 和 size 屬性;詳見 管理檔案 (Managing files)

注意:在上傳檔案時,要警惕儲存檔案的位置和檔案的型別,這麼做的原因是為了避免安全漏洞。對每一個上傳檔案都要驗證,這樣你才能確保上傳的檔案是你想要的檔案。舉個例子,如果你盲目地讓別人上傳檔案,而沒有對上傳檔案進行驗證,如果儲存檔案的目錄處於 web 伺服器的根目錄下,萬一有人上傳了一個 CGI 或是 PHP 指令碼,然後通過訪問指令碼網址來執行上傳的指令碼,那可就太危險了。千萬不要讓這樣的事情發生!

這部分是在 Django 1.0 中新增的: 在這個版本中,新加了 max_length 引數。

預設情況下,FileField 例項在資料庫中的對應列是 varchar(100) ,和其他欄位一樣,你可以利用 max_length 引數改變欄位的最大長度。

FilePathField

class FilePathField(path=None[match=Nonerecursive=Falsemax_length=100**options])

它是一個 CharField ,它用來選擇檔案系統下某個目錄裡面的某些檔案。它有三個專有的引數,只有第一個引數是必須的:

FilePathField.path
這個引數是必需的。它是一個目錄的絕對路徑,而這個目錄就是 FilePathField 用來選擇檔案的那個目錄。比如: "/home/images".
FilePathField.match
可選引數。它是一個正則表示式字串, FilePathField 用它來過濾檔名稱,只有符合條件的檔案才出現在檔案選擇列表中。要注意正則表示式只匹配檔名,而不是匹配檔案路徑。例如: "foo.*\.txt$" 只匹配名為 foo23.txt 而不匹配 bar.txt 和 foo23.gif
FilePathField.recursive
可選引數。它的值是 True 或 False。預設值是 False。它指定是否包含 path 下的子目錄。

當然,這三個引數可以同時使用。

前面已經提到了 match 只匹配檔名稱,而不是檔案路徑。所以下面這個例子:

FilePathField(path="/home/images", match="foo.*", recursive=True)

將匹配 /home/images/foo.gif ,而不匹配 /home/images/foo/bar.gif。這是因為 match 只匹配檔名 (foo.gif 和 bar.gif).

這部分是在 Django 1.0 中新增的: 在這個版本中,新加了 max_length 引數。

預設情況下, FilePathField 例項在資料庫中的對應列是s varchar(100) 。和其他欄位一樣,你可以利用 max_length 引數改變欄位的最大升序。

FloatField

class FloatField([**options])
在 Django 1.0 在已改動: 請檢視版本文件

該欄位在 Python 中使用by a float 例項來表示一個浮點數。

Django 管理後臺用 <input type="text"> (一個單行輸入框) 表示該欄位。

ImageField

class ImageField(upload_to=None[height_field=Nonewidth_field=Nonemax_length=100**options])

和 FileField 一樣,只是會驗證上傳物件是不是一個合法的圖象檔案。它有兩個可選引數:

ImageField.height_field:儲存圖片高度的欄位名稱。在儲存物件時,會根據該欄位設定的高度,對圖片檔案進行縮放轉換。
ImageField.width_field:儲存圖片寬度的欄位名稱。在儲存物件時,會根據該欄位設定的寬度,對圖片檔案進行縮放轉換。

除了那些在 FileField 中有效的引數之外, ImageField 還可以使用 File.height and File.width 兩個屬性。詳見管理檔案 (Managing files)(但並沒有找到這兩個引數的介紹)。使用該欄位要求安裝 Python Imaging Library(PIL).

這部分是在 Django 1.0 中新增的: 在新版本中新加了 max_length 引數。預設情況下, ImageField 例項對應著資料庫中的 created as varchar(100) 列。和其他欄位一樣,你可以使用 max_length 引數來改變欄位的最大長度。

IntegerField

class IntegerField([**options])

整數字段。Django 管理後臺用 <input type="text"> (一個單行輸入框) 表示該欄位。

IPAddressField

class IPAddressField([**options])

以字串形式(比如 192.0.2.30)表示 IP 地址欄位。Django 管理後臺使用 <input type="text"> (一個單行輸入框) 表示該欄位。

NullBooleanField

class NullBooleanField([**options])

與 BooleanField 相似,但多了一個 NULL 選項。建議用該欄位代替使用 null=True 選項的 BooleanField 。Django 管理後臺使用 <select> 選擇框來表示該欄位,選擇框有三個選項,分別是 "Unknown", "Yes" 和 "No" 。

PositiveIntegerField

class PositiveIntegerField([**options]),和 IntegerField 相似,但欄位值必須是非負數。

PositiveSmallIntegerField

class PositiveSmallIntegerField([**options]),和 PositiveIntegerField 類似,但數值的取值範圍較小,受限於資料庫設定。

SlugField

class SlugField([max_length=50**options])

Slug 是一個新聞術語,是指某個事件的短標籤。它只能由字母,數字,下劃線或連字元組成。通賞情況下,它被用做網址的一部分。

和 CharField 類似,你可以指定 max_length (要注意資料庫相容性和本節提到的 max_length )。如果沒有指定 max_length ,Django 會預設欄位長度為50。該欄位會自動設定 Field.db_index to True。基於其他欄位的值來自動填充 Slug 欄位是很有用的。你可以在 Django 的管理後臺中使用 prepopulated_fields 來做到這一點。

SmallIntegerField

class SmallIntegerField([**options]),和 IntegerField 類似,但數值的取值範圍較小,受限於資料庫的限制。

文字欄位TextField

class TextField([**options])

大文字欄位。Django 的管理後臺使用 <textarea> (一個多行文字框) 表示該欄位。

MySQL 使用者請注意:如果你正在使用 MySQLdb 1.2.1p2 和 utf8_bin 字符集(非預設設定),有幾點注意事項要格外留意,詳見 MySQL database notes 。

TextField中輸入換行出現問題:

1. 在TextField中輸入帶換行的文字,存到資料庫後發現是\r\n。但是我的django是在linux上執行的,其他程式都是預設換行是\n的。我如何指定TextField中輸入的換行是\n而不是兩個?

2.

方法1. 使用模版內部內建的filter: linebreaks

Replaces line breaks in plain text with appropriate HTML; a single newline becomes an HTML line break (<br />) and a new line followed by a blank line becomes a paragraph break (</p>).

{% for news in newss %}
    <p>{{ news.content|linebreaks }}</p>
方法2. 修改model程式碼

suggest you to override the save method of your model,replacing new line characters to the preferred format:

class MyModel(models.Model):

    body_text = models.TextField()

     ...

      def save(self):

                 self.body_text = self.body_text.replace("\r\n", "\n")

                 self.body_text = self.body_text.replace("\r", "\n")

                super(MyModel, self).save()

[http://markmail.org/message/pro4hiqv3s6v6eb6]

方法3. template rendering 自動 escape HTML tag,需要關掉,比如 |safe  試試

[http://markmail.org/message/ovti7o33qfonsj3c]


URLField

class URLField([verify_exists=Truemax_length=200**options]),儲存 URL 的 CharField 。它有一個額外的可選引數:
URLField.verify_exists
如果為 True (預設值),Django 在儲存物件時會檢測該 URL 是否可訪問(比如,網址可以正常訪問,不返回404錯誤)。值得注意的是,如果你使用的是一個單執行緒開發伺服器,那麼驗證網址會掛起當前執行緒。當然,對於生產用的多執行緒伺服器來說,這就不是一個問題了。

Django 管理後臺使用 <input type="text"> (一個單行輸入框) 表示該欄位。

和所有 CharField 子類一樣,URLField 接受可選的 max_length 引數,該引數預設值是200。

UUIDField

New in Django 1.8.

XMLField

class XMLField(schema_path=None[**options])

這是一個根據給定的 schema 驗證所輸文字是否是合法 XML 的 TextField 欄位。它有一個必需的引數:

schema_path:用來驗證 XML 的 RelaxNG schema 的檔案路徑。

關聯關係欄位 (Relationship fields)

Django 也定義了一組用來表示關聯關係的欄位。

ForeignKey

class ForeignKey(othermodel[**options])

這是一個多對一關係。必須為它提供一個位置引數:被關聯的 model 類。

Note:外來鍵:如果公共關鍵字在一個關係中是主關鍵字,那麼這個公共關鍵字被稱為另一個關係的外來鍵。由此可見,外來鍵表示了兩個關係之間的相關聯絡。以另一個關係的外來鍵作主關鍵字的表被稱為主表,具有此外來鍵的表被稱為主表的從表。外來鍵又稱作外關鍵字。

要建立遞迴關聯時--與物件自己做多對一關係,那就使用 models.ForeignKey('self') 。

如果你要與某個尚未定義的 model 建立關聯 ,就使用 model 的名稱,而不是使用 model 物件本身:

class Car(models.Model):
    manufacturer = models.ForeignKey('Manufacturer')
    # ...

class Manufacturer(models.Model):
    # ...
這部分是在 Django 1.0 中新建的: 請檢視版本文件

要與其他應用中的 model 相關聯,你要用完整的應用標籤來顯式地定義關聯。例如,如果上面的 Manufacturer model 定義在另外一個名為 production 的應用中,你只要用:

class Car(models.Model):
    manufacturer = models.ForeignKey('production.Manufacturer')

在解決兩個應用雙向依賴時,這種引用方法非常有用。

資料庫表現 (Database Representation)

Django 使用該欄位名稱+ "_id" 做為資料庫中的列名稱。在上面的例子中, Car model 對應的資料表中會有一個 manufacturer_id 列。(你可以通過顯式地指定 db_column 來改變該欄位的列名稱)。不過,除非你想自定義 SQL ,否則沒必要更改資料庫的列名稱。

引數 (Arguments)

ForeignKey 接受下列這些可選引數,這些引數定義了關係是如何執行的。

ForeignKey.limit_choices_to

它是一個包含篩選條件和對應值的字典 (詳見see 製作查詢(Making queries)),用來在 Django 管理後臺篩選關聯物件。例如,利用 Python 的 datetime 模組,過濾掉不符合篩選條件關聯物件:

limit_choices_to = {'pub_date__lte': datetime.now}

只有 pub_date 在當前日期之前的關聯物件才允許被選。

limit_choices_to 對於在管理後臺顯示為 inline 的關聯物件不起作用。

ForeignKey.to_field
指定當前關係與被關聯物件中的哪個欄位關聯。預設情況下,to_field 指向被關聯物件的主鍵。

ManyToManyField

class ManyToManyField(othermodel[**options])

資料庫表示 (Database Representation)

Django 建立一箇中間表來表示多對多關係。預設情況下,中間表的名稱由兩個關係表名結合而成。由於某些資料庫對錶名的長度有限制,所以中間表的名稱會自動限制在64個字元以內,幷包含一個不重複的雜湊字串。這意味著,你可能看到類似 author_books_9cdf4 這樣的表名稱;這是很正常的。你可以使用 db_table 選項手動指定中間表名稱。

引數 (Arguments)

ManyToManyField 接受下列可選引數,這些引數定義了關係是如何執行的。

ManyToManyField.limit_choices_to

limit_choices_to 對於通過 through 引數指定了中介表的 ManyToManyField 不起作用。

ManyToManyField.symmetrical

只要定義遞迴的多對多關係時起作用。假調有下面這樣一個 model :

class Person(models.Model):
    friends = models.ManyToManyField("self")

Django 處理該 model 時,Django 會發現這個一個關聯自己的遞迴 ManyToManyField ,所以 Django 不會給該欄位新增一個指向 Person 類的 person_set 屬性,而是把 ManyToManyField視為對稱的--也就是說,如果我是你的朋友,那麼你自然也就是我的朋友。

如果不想將遞迴的多對多關係設為對稱的,那你就指定 symmetrical 為 False。這樣就會強迫 Django 新增反向名稱,從而將該 ManyToManyField 關聯改為非對稱的。

ManyToManyField.through

Django 會自動生成一張表來管理多對多關係。但是,如果你想手動指定中間表,你可以用 through 選項來指定 model 使用另外某個 model 來管理多對多關係。而這個 model 就是中間表所對應的 model 。(我將through所指定的中間表稱為中介表)。

ManyToManyField.db_table
指定資料庫中儲存多對多關係資料的表名稱。如果沒有提供該選項,Django 就會根據兩個關係表的名稱生成一個新的表名,做為中間表的名稱。

OneToOneField

class OneToOneField(othermodel[parent_link=False**options])

用來定義一對一關係。籠統地講,它與聲明瞭 unique=True 的 ForeignKey 非常相似,不同的是使用反向關聯的時候,得到的不是一個物件列表,而是一個單獨的物件。

在某個 model 擴充套件自另一個 model 時,這個欄位是非常有用的;例如: 多表繼承 (Multi-table inheritance) 就是通過在子 model 中新增一個指向父 model 的一對一關聯而實現的。

此外,OneToOneField 接受 ForeignKey 可接受的引數,只有一個引數是 OnetoOneField 專有的:

如果為 True ,並且作用於繼承自某個父 model 的子 model 上(這裡不能是延後繼承,父 model 必須真實存在),那麼該欄位就會變成指向父類例項的引用(或者叫連結),而不是象其他 OneToOneField 那樣用於擴充套件父類並繼承父類屬性。

編寫自定義 model 欄位(Writing custom model fields)

[http://wrongwaycn.github.io/django11/howto/custom-model-fields/index.html]

Django資料庫欄位選項(Field options)

下列引數對所有欄位型別都是有效的,同時這些引數也是可選的。

null

如果為 True ,Django 就會將空值(empty)儲存為資料庫中的 NULL 。預設值是 False

要注意空字串(empty string)總是被儲存為空字串,而不是 NULL。 null=True 只對非字串欄位有意義,比如整數(integer),布林值(boolean),日期(dates)。如果你允許表單提交空值,無論是哪種欄位,你還要再設定 blank=True ,這是因為 null 僅僅影響資料庫儲存 (詳見 blank)。

除非你有很充分的理由,否則。在字串欄位上宣告 null=True ,就意味著有兩種意義的空值:NULL,和空字串(empty string)。大多數情況下,存在兩種空值是多餘的。Django 按慣例是使用空字串,而非 NULL 。

注意:在使用 Oracle 資料庫時,null=True 選項將被強加到有可能是空值的字串欄位,而且會在資料庫中儲存 NULL ,來表示空字串。

blank

如果為 True,欄位允許不填。預設為 False 。

要注意該選項與 null 不同。 null 純粹是資料庫範疇的概念,而 blank 是資料驗證範疇的。如果某個欄位聲明瞭 blank=True,那麼 Django 的管理後臺就允許該欄位填寫空值;否則,如果宣告為 blank=False,該欄位就是必填的。

choices

它是一個可迭代的二元組(比如,列表或是元組),用來給欄位提供選擇項。
實現Django後臺管理的下拉框選擇。如果設定了 choices ,Django 的管理後臺就會顯示選擇框,而不是標準的文字框,而且這個選擇框的選項就是 choices 中的元組。‘choices' must  be an iterable containing (actual value, human readable name) tuples.每個元組中的第一個元素,是儲存在資料庫中的值;第二個元素是該選項更易理解的描述。
choices 列表可以定義為 model 類的一部分,也可以定義在 model 類之外:
class Foo(models.Model):
    GENDER_CHOICES = (
        ('M', 'Male'),
        ('F', 'Female'),
    )
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
你也可以將 choices 整理成命名組,這樣程式碼更有條理,結構更清晰:
MEDIA_CHOICES = (
    ('Audio', (
            ('vinyl', 'Vinyl'),
            ('cd', 'CD'),
        )
    ),
    ('Video', (