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
CharField
- class CharField(max_length=None[, **options])
- 它是一個字串欄位,對小字串和大字串都適用。對於更大的文字,應該使用 TextField 。
Django 的管理後臺用 <input
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=False, auto_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=False, auto_now_add=False, **options])
該欄位利用 datetime.datetime 例項表示日期和時間。該欄位所按受的引數和 DateField 一樣。
Django 的管理後臺使用兩個 <input type="text"> 分別表示日期和時間,同樣也帶有 JavaScript 快捷選項。
TimeField
- class TimeField([auto_now=False, auto_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=None, decimal_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 (稍後提到) 要按照以下的步驟:
- 在專案配置檔案中,你要定義 MEDIA_ROOT ,將它的值設為用來存放上傳檔案的目錄的完整路徑。(基於效能的考慮,Django 沒有將檔案儲存在資料庫中。) ,然後定義 MEDIA_URL ,將它的值設為表示該目錄的網址。要確保 web 伺服器所用的帳號擁有對該目錄的寫許可權。
- 儲存在資料庫當中的僅僅只是檔案的路徑(而且是相對於 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 目錄下。
如果你想得到上傳檔案的本地檔名稱,檔案網址,或是檔案的大小,你可以使用 name, url 和 size 屬性;詳見 管理檔案 (Managing files)。
注意:在上傳檔案時,要警惕儲存檔案的位置和檔案的型別,這麼做的原因是為了避免安全漏洞。對每一個上傳檔案都要驗證,這樣你才能確保上傳的檔案是你想要的檔案。舉個例子,如果你盲目地讓別人上傳檔案,而沒有對上傳檔案進行驗證,如果儲存檔案的目錄處於 web 伺服器的根目錄下,萬一有人上傳了一個 CGI 或是 PHP 指令碼,然後通過訪問指令碼網址來執行上傳的指令碼,那可就太危險了。千萬不要讓這樣的事情發生!
這部分是在 Django 1.0 中新增的: 在這個版本中,新加了 max_length 引數。預設情況下,FileField 例項在資料庫中的對應列是 varchar(100) ,和其他欄位一樣,你可以利用 max_length 引數改變欄位的最大長度。
FilePathField
- class FilePathField(path=None[, match=None, recursive=False, max_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])¶
該欄位在 Python 中使用by a float 例項來表示一個浮點數。
Django 管理後臺用 <input type="text"> (一個單行輸入框) 表示該欄位。
ImageField
- class ImageField(upload_to=None[, height_field=None, width_field=None, max_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而不是兩個?
方法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=True, max_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 專有的:
- OneToOneField.parent_link
- 如果為 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', (