Python的Django框架中設定日期和欄位可選的方法

NO IMAGE

設定欄位可選

在擺弄了一會之後,你或許會發現管理工具有個限制:編輯表單需要你填寫每一個欄位,然而在有些情況下,你想要某些欄位是可選的。 舉個例子,我們想要Author模組中的email欄位成為可選,即允許不填。 在現實世界中,你可能沒有為每個作者登記郵箱地址。

為了指定email欄位為可選,你只要編輯Book模組(回想第五章,它在mysite/books/models.py檔案裡),在email欄位上加上blank=True。程式碼如下:


class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(**blank=True** )

這些程式碼告訴Django,作者的郵箱地址允許輸入一個空值。 所有欄位都預設blank=False,這使得它們不允許輸入空值。

這裡會發生一些有趣的事情。 直到現在,除了__unicode__()方法,我們的模組充當資料庫中表定義的角色,即本質上是用Python的語法來寫CREATE TABLE語句。 在新增blank=True過程中,我們已經開始在簡單的定義資料表上擴充套件我們的模組了。 現在,我們的模組類開始成為一個富含Author物件屬性和行為的集合了。 email不但展現為一個資料庫中的VARCHAR型別的欄位,它還是頁面中可選的欄位,就像在管理工具中看到的那樣。

當你新增blank=True以後,重新整理頁面Add author edit form (http://127.0.0.1:8000/admin/books/author/add/ ),將會發現Email的標籤不再是粗體了。 這意味它不是一個必填欄位。 現在你可以新增一個作者而不必輸入郵箱地址,即使你為這個欄位提交了一個空值,也再不會得到那刺眼的紅色資訊“This field is required”。
設定日期型和數字型欄位可選

雖然blank=True同樣適用於日期型和數字型欄位,但是這裡需要詳細講解一些背景知識。

SQL有指定空值的獨特方式,它把空值叫做NULL。NULL可以表示為未知的、非法的、或其它程式指定的含義。

在SQL中, NULL的值不同於空字串,就像Python中None不同於空字串(””)一樣。這意味著某個字元型欄位(如VARCHAR)的值不可能同時包含NULL和空字串。

這會引起不必要的歧義或疑惑。 為什麼這條記錄有個NULL,而那條記錄卻有個空字串? 它們之間有區別,還是資料輸入不一致? 還有: 我怎樣才能得到全部擁有空值的記錄,應該按NULL和空字串查詢麼?還是僅按字串查詢?

為了消除歧義,Django生成CREATE TABLE語句自動為每個欄位顯式加上NOT NULL。 這裡有個生成Author模組的例子:


CREATE TABLE "books_author" (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(40) NOT NULL,
"email" varchar(75) NOT NULL
)
;

在大多數情況下,這種預設的行為對你的應用程式來說是最佳的,因為它可以使你不再因資料一致性而頭痛。 而且它可以和Django的其它部分工作得很好。如在管理工具中,如果你留空一個字元型欄位,它會為此插入一個空字串(而* 不是*NULL)。

但是,其它資料型別有例外:日期型、時間型和數字型欄位不接受空字串。 如果你嘗試將一個空字串插入日期型或整數型欄位,你可能會得到資料庫返回的錯誤,這取決於那個資料庫的型別。 (PostgreSQL比較嚴禁,會丟擲一個異常;MySQL可能會也可能不會接受,這取決於你使用的版本和運氣了。)在這種情況下,NULL是唯一指定空值的方法。 在Django模組中,你可以通過新增null=True來指定一個欄位允許為NULL。

因此,這說起來有點複雜: 如果你想允許一個日期型(DateField、TimeField、DateTimeField)或數字型(IntegerField、DecimalField、FloatField)欄位為空,你需要使用null=True * 和* blank=True。

為了舉例說明,讓我們把Book模組修改成允許 publication_date為空。修改後的程式碼如下:


class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField(**blank=True, null=True** )

新增null=True比新增blank=True複雜。因為null=True改變了資料的語義,即改變了CREATE TABLE語句,把publication_date欄位上的NOT NULL刪除了。 要完成這些改動,我們還需要更新資料庫。

出於某種原因,Django不會嘗試自動更新資料庫結構。所以你必須執行ALTER TABLE語句將模組的改動更新至資料庫。 像先前那樣,你可以使用manage.py dbshell進入資料庫服務環境。 以下是在這個特殊情況下如何刪除NOT NULL:


ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;

(注意:以下SQL語法是PostgreSQL特有的。)

我們將在第十章詳細講述資料庫結構更改。

現在讓我們回到管理工具,新增book的編輯頁面允許輸入一個空的publication date。

您可能感興趣的文章:

全面解讀Python Web開發框架Djangopython常用web框架簡單效能測試結果分享(包含django、flask、bottle、tornado)用Python的Django框架完成視訊處理任務的教程分析Python的Django框架的執行方式及處理流程使用Python的Django框架實現事務交易管理的教程詳解Python的Django框架中的通用檢視詳解Python的Django框架中的templates設定Python的Django框架中的表單處理示例詳解Python的Django框架中的Cookie相關處理python模擬Django框架例項