本文介紹如何為 LocalLibrary 網(wǎng)站定義模型。它解釋了模型是什么、聲明的方式以及一些主要字段類型。它還簡(jiǎn)要展示了您可以訪問(wèn)模型數(shù)據(jù)的幾個(gè)主要方法。
概述節(jié)Django Web應(yīng)用程序通過(guò)被稱為模型的Python對(duì)象訪問(wèn)和管理數(shù)據(jù)。模型定義存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu),包括字段類型以及可能還有最大大小,默認(rèn)值,選擇列表選項(xiàng),幫助文檔,表單的標(biāo)簽文本等。模型的定義與底層數(shù)據(jù)庫(kù)無(wú)關(guān)—你可以選擇其中一個(gè)作為項(xiàng)目設(shè)置的一部分。一旦你選擇了要使用的數(shù)據(jù)庫(kù),你就不需要直接與之交談—只需編寫模型結(jié)構(gòu)和其他代碼,Django可以處理與數(shù)據(jù)庫(kù)通信的所有繁瑣工作。 本教程將介紹如何定義和訪問(wèn) LocalLibrary 網(wǎng)站 實(shí)例的模型。 設(shè)計(jì)LocalLibrary模型節(jié)在你投身開始編寫模型之前,花幾分鐘時(shí)間考慮我們需要存儲(chǔ)的數(shù)據(jù)以及不同對(duì)象之間的關(guān)系。 我們知道,我們需要存儲(chǔ)書籍的信息(標(biāo)題,摘要,作者,語(yǔ)言,類別,ISBN),并且我們可能有多個(gè)副本(具有全球唯一的ID,可用性狀態(tài)等)。我們可以存儲(chǔ)更多關(guān)于作者的信息,而不僅僅是他的名字,或多個(gè)作者的相同或相似的名稱。我們希望能根據(jù)書名,作者名,語(yǔ)言和類別對(duì)信息進(jìn)行排序。 在設(shè)計(jì)模型時(shí),為每個(gè)“對(duì)象”(相關(guān)信息組)分別設(shè)置模型是有意義的。在這種情況下,明顯的對(duì)象是書籍,書情況和作者。 你可能想要使用模型來(lái)表示選擇列表選項(xiàng)(例如:選擇下拉列表),而不是硬編碼編寫選項(xiàng)進(jìn)網(wǎng)站—這是當(dāng)所有選項(xiàng)面臨未知或改變時(shí)候的建議。在本網(wǎng)站,模型的明顯之處包括書籍類型(例如:科幻小說(shuō),法國(guó)詩(shī)歌等)和語(yǔ)言(英語(yǔ),法語(yǔ),日語(yǔ))。 一旦我們已經(jīng)決定了我們的模型和字段,我們需要考慮它們的關(guān)聯(lián)性。Django允許你來(lái)定義一對(duì)一的關(guān)聯(lián)(OneToOneField),一對(duì)多(ForeignKey)和多對(duì)多(ManyToManyField)。 思考一下,在網(wǎng)站中,我們將定義模型展示在下面UML關(guān)聯(lián)圖中(下圖)。以上,我們創(chuàng)建了書的模型(書的通用細(xì)節(jié)),書的情況(系統(tǒng)中特定物理副本的書籍狀態(tài)—借—有),和作者。我們也決定了個(gè)類型模型,以便通過(guò)管理界面創(chuàng)建/選擇值。我們決定沒有一個(gè)模型 BookInstance:status—我們硬編碼了值(LOAN_STATUS),因?yàn)槲覀儾幌M@改變。在每個(gè)框中,你可以看到模型名稱,字段名稱和類型,以及方法和返回類型。 該圖顯示模型之間的關(guān)系,包括它們的多重性。多重性是圖中的數(shù)字,顯示可能存在于關(guān)系中的每個(gè)模型的數(shù)量(最大值和最小值)。例如,盒子之間的連接線顯示書和類型相關(guān)。書模型中數(shù)字表明,一本書必須有一個(gè)或多個(gè)流派(盡可能多),而類型旁邊的線的另一端的數(shù)字表明它可以有零個(gè)或更多的關(guān)聯(lián)書。 注意: 下一節(jié)提供一個(gè)基本解釋模型的定義與使用,當(dāng)你讀到,考慮如何構(gòu)建上圖中的每個(gè)模型。 模型入門節(jié)本節(jié)簡(jiǎn)要概述了模型定義和一些重要的字段和字段參數(shù)。 模型定義節(jié)模型通常在 models.py 中定義。它們是繼承自
在下面章節(jié)中,我們將細(xì)致解釋模型的每個(gè)功能。 字段模型可以有任意數(shù)量的字段,任何類型的字段—每個(gè)字段都表示我們要存儲(chǔ)在我們的一個(gè)數(shù)據(jù)庫(kù)中的一列數(shù)據(jù)。每個(gè)數(shù)據(jù)庫(kù)記錄(行)將由每個(gè)字段值之一組成。我們來(lái)看看例子。
上面例子中單個(gè)字段叫 my_field_name ,類型為 models.CharField—這意味著這個(gè)字段將會(huì)包含字母數(shù)字字符串。使用特定的類分配字段類型,這些類決定了用于將數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)庫(kù)中的記錄的類型,以及從HTML表單接收到值(即構(gòu)成有效值)時(shí)使用的驗(yàn)證標(biāo)準(zhǔn)。字段類型還可以獲取參數(shù),進(jìn)一步指定字段如何存儲(chǔ)或可以使用。在這種情況下,我們給出了兩個(gè)論點(diǎn):
字段名稱用于在查詢和模版中引用它。字段還有一個(gè)標(biāo)簽,它被指定一個(gè)參數(shù)(verbose_name)或者通過(guò)大寫字段的變量名的第一個(gè)字母,并用空格 替換下劃線(例如 my_field_name ->My field name ,這就是默認(rèn)標(biāo)簽)。 如果模型在表單中呈現(xiàn)(例如:在管理站點(diǎn)中),則聲明該字段的順序?qū)⒂绊懫淠J(rèn)順序,但可能會(huì)被覆蓋。 公共字段參數(shù)當(dāng)聲明很多/大多數(shù)不同的字段類型時(shí),可以使用以下常用參數(shù):
還有許多其他選項(xiàng) — 你可以在 完整的字段選項(xiàng)。 常用字段類型以下列表描述了一些更常用的字段類型。
還有許多其他類型的字段,包括不同類型數(shù)字的字段(大整數(shù),小整數(shù),浮點(diǎn)數(shù)),布爾值,URL,唯一Ids和其他“時(shí)間相關(guān)” 信息(持續(xù)時(shí)間,時(shí)間等)。你可以查閱完整列表. 元數(shù)據(jù)你可以通過(guò)聲明 class Meta 聲明模型級(jí)別的元數(shù)據(jù) ,如圖所示。
此元數(shù)據(jù)的最有用功能之一是控制在查詢模型類型時(shí)返回的記錄的默認(rèn)排序。你可以通過(guò)在ordering 屬性的字段名稱列表中指定匹配順序來(lái)執(zhí)行此操作,如上所示。排序?qū)⒁蕾囎侄蔚念愋停ㄗ址侄伟醋帜疙樞蚺判?,而日期字段按時(shí)間順序排序)。如上所示,你可以使用減號(hào)(-)對(duì)字段名稱進(jìn)行前綴,以反轉(zhuǎn)排序順序。 例如,如果我們選擇默認(rèn)排列這樣的書單:
書單通過(guò)標(biāo)題依據(jù)-字母排序-排列,從A到Z,還有每個(gè)標(biāo)題的出版日期,從最新到最舊。 另一個(gè)常見的屬性是 verbose_name ,一個(gè)verbose_name 說(shuō)明單數(shù)和復(fù)數(shù)形式的類。
其他有用的屬性允許你為模型創(chuàng)建和應(yīng)用新的 “訪問(wèn)權(quán)限”(自動(dòng)應(yīng)用默認(rèn)權(quán)限),允許基于其他的字段排序,或聲明該類是”抽象的“(你無(wú)法創(chuàng)建的記錄基類,并將由其他型號(hào)派生)。 許多其他元數(shù)據(jù)選項(xiàng)控制模型中必須使用哪些數(shù)據(jù)庫(kù)以及數(shù)據(jù)的存儲(chǔ)方式。(如果你需要模型映射一個(gè)現(xiàn)有數(shù)據(jù)庫(kù),這會(huì)有用)。 完整有用的元數(shù)據(jù)選項(xiàng)在這里 Model metadata options (Django docs). 方法一個(gè)模型也可以有方法。 最起碼,在每個(gè)模型中,你應(yīng)該定義標(biāo)準(zhǔn)的Python 類方法 __str__() 來(lái)為每個(gè)對(duì)象返回一個(gè)人類可讀的字符串。此字符用于表示管理站點(diǎn)的各個(gè)記錄(以及你需要引用模型實(shí)例的任何其他位置)。通常這將返回模型中的標(biāo)題或名稱字段。
Django方法中另一個(gè)常用方法是 get_absolute_url(),這函數(shù)返回一個(gè)在網(wǎng)站上顯示個(gè)人模型記錄的URL(如果你定義了該方法,那么Django 將自動(dòng)在“管理站點(diǎn)”中添加“在站點(diǎn)中查看“按鈕在模型的記錄編輯欄)。典型示例以下:
注意: 假設(shè)你將使用URL/myapplication/mymodelname/2 來(lái)顯示模型的單個(gè)記錄(其中“2”是 id 特定 記錄),則需要?jiǎng)?chuàng)建一個(gè)URL映射器來(lái)將響應(yīng)和id傳遞給 “模型詳細(xì)視圖” (這將做出顯示記錄所需的工作)。以上示例中,reverse() 函數(shù)可以“反轉(zhuǎn)”你的url映射器(在上訴命名為“model-detail-view” 的案例中,以創(chuàng)建正確格式的URL。 當(dāng)然要做這個(gè)工作,你還是要寫URL映射,查看和模版! 你可以定義一些你喜歡的其他方法,并從你的代碼或模版調(diào)用它們(只要它們不帶任何參數(shù))。 模型管理節(jié)一旦你定義了模型類,你可以使用它們來(lái)創(chuàng)建,更新或刪除記錄,并運(yùn)行查詢獲取所有記錄或特定的記錄子集。當(dāng)我們定義我們的視圖,我們將展示給你在這個(gè)教程如何去做。 創(chuàng)建和修改記錄要?jiǎng)?chuàng)建一個(gè)記錄,你可以定義一個(gè)模型實(shí)例,然后調(diào)用save()。
注意: 如果你沒有將任何字段聲明為一個(gè)primary_key,新記錄將自動(dòng)給出一個(gè)字段名稱id。保存上訴記錄后,你可以查詢此字段,值為1。 你可以使用 -點(diǎn)-語(yǔ)法 訪問(wèn)此新記錄中的字段,并更改值。你必須調(diào)用 save() 將修改后的值存儲(chǔ)到數(shù)據(jù)庫(kù)。
搜索記錄你可以使用模型的 objects(基類提供)搜索符合特定條件的記錄。 注意: 使用“抽象“模型和字段名稱解釋如何搜尋記錄可能有點(diǎn)混亂。在下面的討論中,我們將引用一個(gè)Book 模型帶有 title 和 genre 字段,其中 genre 也是一個(gè)帶有單個(gè)字段名的模型。 我們通過(guò) QuerySet 獲取一個(gè)模型的所有記錄,使用 object.all()。這個(gè)QuerySet是個(gè)可迭代的對(duì)象,意味著它包括一些可以迭代/循環(huán)的對(duì)象。
Django的 filter() 方法允許我們根據(jù)特定的標(biāo)準(zhǔn)過(guò)濾 返回QuerySet 的匹配指定的文本或數(shù)字字段。例如,要過(guò)濾在標(biāo)題包含 “wild”(野生)和對(duì)其計(jì)數(shù),我們可以像下面那樣做。
字段匹配和匹配類型都定義在 過(guò)濾器參數(shù)名稱中,使用以下格式:field_name__match_type 注意之間和之上的雙下劃線)。 在某些情況下,你需要去過(guò)濾—定義了一對(duì)多關(guān)系到另一個(gè)模型的字段。在這種情況下,你可以使用附加雙重下劃線在相關(guān)模型中"索引"字段。例如,過(guò)濾特定類型模式的書,你將不得不索引類型字段名,如下:
注意: 你可以用下劃線(_)根據(jù)你喜歡的許多層次的關(guān)系(ForeignKey/ManyToManyField)。例如:不同類型的書,定義使用一個(gè)進(jìn)一步“封面”關(guān)系可能會(huì)有一個(gè)參數(shù)名稱: 這里有許多關(guān)于你查詢的事,包括相關(guān)模型的向后搜素,鏈接過(guò)濾器,返回一組較小的值等等。有關(guān)詳細(xì)信息,請(qǐng)參閱制作查詢 (Django Docs). 定義LocalLibrary模型節(jié)在本節(jié)中,我們會(huì)開始定義模型庫(kù)。打開 models.py (in /locallibrary/catalog/)。這 頁(yè)面頂部的樣板導(dǎo)入模型模塊,其中包含models.Model模型將繼承的模型基類。
Genre 模型節(jié)復(fù)制下面顯示的Genre模型代碼,并將其粘貼到 models.py 文件的底部。這個(gè)模型用于存儲(chǔ)關(guān)于書籍類別的信息。例如是否是小說(shuō)或非小說(shuō),浪漫史或軍事歷史等。如上所述,我們創(chuàng)建了Genre作為模型,而不是免費(fèi)文本或選擇列表,以便可以通過(guò)數(shù)據(jù)庫(kù)管理可能的值,而不是硬編碼。
這個(gè)模型有一個(gè) CharField 字段(name),用于描述類型(最大200字符和有一些幫助文本(help_text)。在模型最后,我們聲明了一個(gè) __str__() 方法,簡(jiǎn)單返回特定記錄的定義類型名,沒有定義詳細(xì)的名稱,因此該字段將以Name表單形式調(diào)用。 Book 模型節(jié)復(fù)制下面的Book模型,然后再次粘貼到文件的底部。Book模型代表了一般普遍意義上的一本可用的書的所有信息,但并不是一個(gè)特定的物理“實(shí)例”或可用于借閱的“復(fù)制“。該模型采用了CharField代表書中的 title 和 isbn (注意 isbn指定使用的第一個(gè)未命名的參數(shù)是 ”ISBN“的標(biāo)簽,因?yàn)槟J(rèn)的標(biāo)簽也就是”isbn“)該模型采用TextField的summary,因?yàn)檫@種文字可能需要相當(dāng)長(zhǎng)。
這個(gè)類型是一個(gè) ManyToManyField ,所以一個(gè)一本書可以有多個(gè)類型和一個(gè)類型可以有許多書。作者被定義ForeignKey,所以每個(gè)書將只有一個(gè)作者,但作者可能有許多書(實(shí)際上一本書可能有多個(gè)作者,但不在這個(gè)實(shí)現(xiàn)中)。 在兩個(gè)字段類型中,相關(guān)模型都使用模型類或包含相關(guān)模型名稱的字符串來(lái)聲明為第一個(gè)未命名參數(shù)。如果關(guān)聯(lián)的類在引用之前尚未在此文件中定義,則必須使用模型的名稱作為字符串!該 author 字段中感興趣的其他參數(shù)是 null=True ,如果沒有作者被選擇,這允許數(shù)據(jù)庫(kù)存儲(chǔ)一個(gè) Null 值,和on_delete=models.SET_NULL 將作者的值設(shè)置為 Null 如果相關(guān)的作者記錄被刪除。 該模型還定義 __str__(),使用書的文本字段來(lái)表示Book記錄。最終的方法,get_absolute_url() 返回一個(gè)可用于訪問(wèn)這些模型的詳細(xì)記錄的URL (為此,我們將必須定義具有該名稱的URL映射 book-detail,并定義關(guān)聯(lián)的視圖和模版)。 BookInstance 模型節(jié)接下來(lái),在其他型號(hào)下復(fù)制 BookInstance 模型(如下)。該 BookInstance 代表一本書,有人可能借用的一個(gè)特定副本,包括有關(guān)副本是否可用在什么日期預(yù)計(jì)還,“印記“或版本的詳細(xì)信息,并為這本書在圖書館給予一個(gè)唯一的ID信息。 一些字段和方法現(xiàn)在會(huì)熟悉。該模型使用
另外我們展示一些新的字段類型:
該模型 注意: Python小知識(shí):
Author 模型節(jié)復(fù)制下方Author模型到 models.py 的現(xiàn)有代碼中。 所有的字段/方法現(xiàn)在應(yīng)該是熟悉le。該模型將作者定義為具有名字,姓氏,出生日期和(可選)死亡日期。它指定,默認(rèn)情況下,
重新運(yùn)行數(shù)據(jù)庫(kù)遷移節(jié)現(xiàn)在你的所有的模型都已經(jīng)創(chuàng)建好了,我們重新運(yùn)行數(shù)據(jù)庫(kù)遷移把它們添加到你的數(shù)據(jù)庫(kù)中:
語(yǔ)言模型 — 挑戰(zhàn)節(jié)想象一下當(dāng)?shù)氐木栀?zèng)者捐贈(zèng)了一些用另一種語(yǔ)言寫的新書(比如說(shuō),波斯語(yǔ))。面臨的挑戰(zhàn)是如何在我們的圖書館網(wǎng)站中最好地表現(xiàn)這些,然后將它們添加到模型中。 有些事情要考慮: 如果“語(yǔ)言”有關(guān)聯(lián)Book,BookInstance或者一些其他的對(duì)象? 概要節(jié)在本文中,我們了解了模型是如何定義的,然后使用這些信息來(lái)設(shè)計(jì)和實(shí)現(xiàn)LocalLibrary網(wǎng)站的相應(yīng)模型。 在這一點(diǎn)上,我們將簡(jiǎn)要地從創(chuàng)建網(wǎng)站轉(zhuǎn)移,并查看Django管理站點(diǎn)。該網(wǎng)站將允許我們向庫(kù)添加一些數(shù)據(jù),然后我們可以使用我們的(尚待創(chuàng)建)視圖和模板顯示。 See also節(jié)
|
|