Django基礎(chǔ)[Python+Django]_第1頁
Django基礎(chǔ)[Python+Django]_第2頁
Django基礎(chǔ)[Python+Django]_第3頁
Django基礎(chǔ)[Python+Django]_第4頁
Django基礎(chǔ)[Python+Django]_第5頁
已閱讀5頁,還剩29頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、中北大學(xué) 由Yubg整理 QQ: 120487362第五章 模型在第三章,我們講述了用 Django 建造網(wǎng)站的基本途徑: 建立視圖和 URLConf 。 正如我們所闡述的,視圖負(fù)責(zé)處理一些主觀邏輯,然后返回響應(yīng)結(jié)果。 作為例子之一,我們的主觀邏輯是要計(jì)算當(dāng)前的日期和時間。在當(dāng)代 Web 應(yīng)用中,主觀邏輯經(jīng)常牽涉到與數(shù)據(jù)庫的交互。 數(shù)據(jù)庫驅(qū)動網(wǎng)站 在后臺連接數(shù)據(jù)庫服務(wù)器,從中取出一些數(shù)據(jù),然后在 Web 頁面用漂亮的格式展示這些數(shù)據(jù)。 這個網(wǎng)站也可能會向訪問者提供修改數(shù)據(jù)庫數(shù)據(jù)的方法。許多復(fù)雜的網(wǎng)站都提供了以上兩個功能的某種結(jié)合。 例如 A 就是一個數(shù)據(jù)庫驅(qū)動站點(diǎn)的良好范例。 本質(zhì)上,每個產(chǎn)品

2、頁面都是數(shù)據(jù)庫中數(shù)據(jù)以 HTML格式進(jìn)行的展現(xiàn),而當(dāng)你發(fā)表客戶評論時,該評論被插入評論數(shù)據(jù)庫中。由于先天具備 Python 簡單而強(qiáng)大的數(shù)據(jù)庫查詢執(zhí)行方法,Django 非常適合開發(fā)數(shù)據(jù)庫驅(qū)動網(wǎng)站。 本章深入介紹了該功能: Django 數(shù)據(jù)庫層。(注意: 盡管對 Django 數(shù)據(jù)庫層的使用中并不特別強(qiáng)調(diào)這點(diǎn),但是我們還是強(qiáng)烈建議您掌握一些數(shù)據(jù)庫和 SQL 原理。 對這些概念的介紹超越了本書的范圍,但就算你是數(shù)據(jù)庫方面的菜鳥,我們也建議你繼續(xù)閱讀。 你也許能夠跟上進(jìn)度,并在上下文學(xué)習(xí)過程中掌握一些概念。)在視圖中進(jìn)行數(shù)據(jù)庫查詢的笨方法正如第三章詳細(xì)介紹的那個在視圖中輸出 HTML 的笨方法(

3、通過在視圖里對文本直接硬編碼HTML),在視圖中也有笨方法可以從數(shù)據(jù)庫中獲取數(shù)據(jù)。很簡單: 用現(xiàn)有的任何 Python 類庫執(zhí)行一條 SQL 查詢并對結(jié)果進(jìn)行一些處理。在本例的視圖中,我們使用了 MySQLdb 類庫(可以從 獲得)來連接 MySQL 數(shù)據(jù)庫,取回一些記錄,將它們提供給模板以顯示一個網(wǎng)頁:from django.shortcuts import render_to_responseimport MySQLdbdef book_list(request):db = MySQLdb.connect(user='me', db='mydb', pass

4、wd='secret', host='localhost')cursor = db.cursor()cursor.execute('SELECT name FROM books ORDER BY name')names = row0 for row in cursor.fetchall()db.close()return render_to_response('book_list.html', 'names': names)這個方法可用,但很快一些問題將出現(xiàn)在你面前:§ 我們將數(shù)據(jù)庫連接參數(shù)硬行編碼于代碼

5、之中。 理想情況下,這些參數(shù)應(yīng)當(dāng)保存在 Django 配置中。§ 我們不得不重復(fù)同樣的代碼: 創(chuàng)建數(shù)據(jù)庫連接、創(chuàng)建數(shù)據(jù)庫游標(biāo)、執(zhí)行某個語句、然后關(guān)閉數(shù)據(jù)庫。 理想情況下,我們所需要應(yīng)該只是指定所需的結(jié)果。§ 它把我們栓死在 MySQL 之上。 如果過段時間,我們要從 MySQL 換到 PostgreSQL,就不得不使用不同的數(shù)據(jù)庫適配器(例如 psycopg 而不是 MySQLdb ),改變連接參數(shù),根據(jù) SQL 語句的類型可能還要修改SQL 。 理想情況下,應(yīng)對所使用的數(shù)據(jù)庫服務(wù)器進(jìn)行抽象,這樣一來只在一處修改即可變換數(shù)據(jù)庫服務(wù)器。 (如果你正在建立一個開源的Django

6、應(yīng)用程序來盡可能讓更多人使用的話,這個特性是非常適當(dāng)?shù)摹#┱缒闼诖模珼jango數(shù)據(jù)庫層正是致力于解決這些問題。 以下提前揭示了如何使用 Django 數(shù)據(jù)庫 API 重寫之前那個視圖。from django.shortcuts import render_to_responsefrom mysite.books.models import Bookdef book_list(request):books = Book.objects.order_by('name')return render_to_response('book_list.html', &

7、#39;books': books)我們將在本章稍后的地方解釋這段代碼。 目前而言,僅需對它有個大致的認(rèn)識。MTV 開發(fā)模式在鉆研更多代碼之前,讓我們先花點(diǎn)時間考慮下 Django 數(shù)據(jù)驅(qū)動 Web 應(yīng)用的總體設(shè)計(jì)。我們在前面章節(jié)提到過,Django 的設(shè)計(jì)鼓勵松耦合及對應(yīng)用程序中不同部分的嚴(yán)格分割。 遵循這個理念的話,要想修改應(yīng)用的某部分而不影響其它部分就比較容易了。 在視圖函數(shù)中,我們已經(jīng)討論了通過模板系統(tǒng)把業(yè)務(wù)邏輯和表現(xiàn)邏輯分隔開的重要性。 在數(shù)據(jù)庫層中,我們對數(shù)據(jù)訪問邏輯也應(yīng)用了同樣的理念。把數(shù)據(jù)存取邏輯、業(yè)務(wù)邏輯和表現(xiàn)邏輯組合在一起的概念有時被稱為軟件架構(gòu)的 Model-Vi

8、ew-Controller (MVC)模式。 在這個模式中, Model 代表數(shù)據(jù)存取層,View 代表的是系統(tǒng)中選擇顯示什么和怎么顯示的部分,Controller 指的是系統(tǒng)中根據(jù)用戶輸入并視需要訪問模型,以決定使用哪個視圖的那部分。為什么用縮寫?像 MVC 這樣的明確定義模式的主要用于改善開發(fā)人員之間的溝通。 比起告訴同事,“讓我們采用抽象的數(shù)據(jù)存取方式,然后單獨(dú)劃分一層來顯示數(shù)據(jù),并且在中間加上一個控制它的層”,一個通用的說法會讓你收益,你只需要說:“我們在這里使用MVC模式吧。”。Django 緊緊地遵循這種 MVC 模式,可以稱得上是一種 MVC 框架。 以下是 Django 中 M

9、、V 和 C 各自的含義:§ M ,數(shù)據(jù)存取部分,由django數(shù)據(jù)庫層處理,本章要講述的內(nèi)容。§ V ,選擇顯示哪些數(shù)據(jù)要顯示以及怎樣顯示的部分,由視圖和模板處理。§ C ,根據(jù)用戶輸入委派視圖的部分,由 Django 框架根據(jù) URLconf 設(shè)置,對給定 URL 調(diào)用適當(dāng)?shù)?Python 函數(shù)。由于 C 由框架自行處理,而 Django 里更關(guān)注的是模型(Model)、模板(Template)和視圖(Views),Django 也被稱為 MTV 框架 。在 MTV 開發(fā)模式中:§ M 代表模型(Model),即數(shù)據(jù)存取層。 該層處理與數(shù)據(jù)相關(guān)的所有

10、事務(wù): 如何存取、如何驗(yàn)證有效性、包含哪些行為以及數(shù)據(jù)之間的關(guān)系等。§ T 代表模板(Template),即表現(xiàn)層。 該層處理與表現(xiàn)相關(guān)的決定: 如何在頁面或其他類型文檔中進(jìn)行顯示。§ V 代表視圖(View),即業(yè)務(wù)邏輯層。 該層包含存取模型及調(diào)取恰當(dāng)模板的相關(guān)邏輯。 你可以把它看作模型與模板之間的橋梁。如果你熟悉其它的 MVC Web開發(fā)框架,比方說 Ruby on Rails,你可能會認(rèn)為 Django 視圖是控制器,而 Django 模板是視圖。 很不幸,這是對 MVC 不同詮釋所引起的錯誤認(rèn)識。 在 Django 對 MVC 的詮釋中,視圖用來描述要展現(xiàn)給用戶的數(shù)

11、據(jù);不是數(shù)據(jù) 如何展現(xiàn) ,而且展現(xiàn) 哪些 數(shù)據(jù)。 相比之下,Ruby on Rails 及一些同類框架提倡控制器負(fù)責(zé)決定向用戶展現(xiàn)哪些數(shù)據(jù),而視圖則僅決定 如何 展現(xiàn)數(shù)據(jù),而不是展現(xiàn) 哪些 數(shù)據(jù)。兩種詮釋中沒有哪個更加正確一些。 重要的是要理解底層概念。數(shù)據(jù)庫配置記住這些理念之后,讓我們來開始 Django 數(shù)據(jù)庫層的探索。 首先,我們需要做些初始配置;我們需要告訴Django使用什么數(shù)據(jù)庫以及如何連接數(shù)據(jù)庫。我們假定你已經(jīng)完成了數(shù)據(jù)庫服務(wù)器的安裝和激活,并且已經(jīng)在其中創(chuàng)建了數(shù)據(jù)庫(例如,用 CREATEDATABASE 語句)。 如果你使用SQLite,不需要這步安裝,因?yàn)镾QLite使用文

12、件系統(tǒng)上的獨(dú)立文件來存儲數(shù)據(jù)。象前面章節(jié)提到的 TEMPLATE_DIRS 一樣,數(shù)據(jù)庫配置也是在Django的配置文件里,缺省是 settings.py 。 打開這個文件并查找數(shù)據(jù)庫配置:DATABASE_ENGINE = ''DATABASE_NAME = ''DATABASE_USER = ''DATABASE_PASSWORD = ''DATABASE_HOST = ''DATABASE_PORT = ''配置綱要如下。DATABASE_ENGINE告訴Django使用哪個數(shù)據(jù)庫引擎。如果你

13、在 Django 中使用數(shù)據(jù)庫,DATABASE_ENGINE必須是 Table 5-1 中所列出的值。表 5-1. 數(shù)據(jù)庫引擎設(shè)置設(shè)置數(shù)據(jù)庫所需適配器 postgresqlPostgreSQLpsycopg 1.x版, postgresql_psycopg2PostgreSQLpsycopg 2.x版, mysqlMySQLMySQLdb ,sqlite3SQLite如果使用Python2.5+則不需要適配器。否則就使用 pysqlite , oracleOraclecx_Oracle ,要注意的是無論選擇使用哪個數(shù)據(jù)庫服務(wù)器,都必須下載和安裝對應(yīng)的數(shù)據(jù)庫適配器。訪問表 5-1 中“所需適配

14、器”一欄中的鏈接,可通過互聯(lián)網(wǎng)免費(fèi)獲取這些適配器。如果你使用Linux,你的發(fā)布包管理系統(tǒng)會提供合適的包。比如說查找 python-postgresql 或者 python-psycopg 的軟件包。配置示例:DATABASE_ENGINE = 'postgresql_psycopg2'DATABASE_NAME將數(shù)據(jù)庫名稱告知 Django 。例如:DATABASE_NAME = 'mydb'如果使用 SQLite,請對數(shù)據(jù)庫文件指定完整的文件系統(tǒng)路徑。例如:DATABASE_NAME = '/home/django/mydata.db'在這個

15、例子中,我們將SQLite數(shù)據(jù)庫放在/home/django目錄下,你可以任意選用最合適你的目錄。DATABASE_USER告訴 Django 用哪個用戶連接數(shù)據(jù)庫。例如:如果用SQLite,空白即可。DATABASE_PASSWORD告訴Django連接用戶的密碼。 SQLite 用空密碼即可。DATABASE_HOST告訴 Django 連接哪一臺主機(jī)的數(shù)據(jù)庫服務(wù)器。如果數(shù)據(jù)庫與 Django 安裝于同一臺計(jì)算機(jī)(即本機(jī)),可將此項(xiàng)保留空白。如果你使用SQLite,此項(xiàng)留空。此處的 MySQL 是一個特例。如果使用的是 MySQL 且該項(xiàng)設(shè)置值由斜杠('/')開頭,MySQ

16、L 將通過 Unix socket 來連接指定的套接字,例如:DATABASE_HOST = '/var/run/mysql'一旦在輸入了那些設(shè)置并保存之后應(yīng)當(dāng)測試一下你的配置。 我們可以在 mysite 項(xiàng)目目錄下執(zhí)行上章所提到的 python manage.py shell 來進(jìn)行測試。 (我們上一章提到過在, manager.py shell 命令是以正確Django配置啟用Python交互解釋器的一種方法。 這個方法在這里是很有必要的,因?yàn)镈jango需要知道加載哪個配置文件來獲取數(shù)據(jù)庫連接信息。)輸入下面這些命令來測試你的數(shù)據(jù)庫配置:>>>from

17、django.db import connection>>>cursor = connection.cursor()如果沒有顯示什么錯誤信息,那么你的數(shù)據(jù)庫配置是正確的。 否則,你就得 查看錯誤信息來糾正錯誤。 表 5-2 是一些常見錯誤。表 5-2. 數(shù)據(jù)庫配置錯誤信息錯誤信息解決方法You havent set the DATABASE_ENGINE setting yet.不要以空字符串配置 DATABASE_ENGINE 的值。 表格 5-1 列出可用的值。Environment variable DJANGO_SETTINGS_MODULE is undefined

18、.使用 python manager.py shell 命令啟動交互解釋器,不要以 python 命令直接啟動交互解釋器。Error loading _ module: No module named _.未安裝合適的數(shù)據(jù)庫適配器 (例如, psycopg 或 MySQLdb )。Django并不自帶適配器,所以你得自己下載安裝。_ isnt an available database backend.把DATABASE_ENGINE 配置成前面提到的合法的數(shù)據(jù)庫引擎。 也許是拼寫錯誤?database _ does not exist設(shè)置 DATABASE_NAME 指向存在的數(shù)據(jù)庫,或者先

19、在數(shù)據(jù)庫客戶端中執(zhí)行合適的 CREATE DATABASE 語句創(chuàng)建數(shù)據(jù)庫。role _ does not exist設(shè)置 DATABASE_USER 指向存在的用戶,或者先在數(shù)據(jù)庫客戶端中執(zhí)創(chuàng)建用戶。could not connect to server查看DATABASE_HOST和DATABASE_PORT是否已正確配置,并確認(rèn)數(shù)據(jù)庫服務(wù)器是否已正常運(yùn)行。第一個應(yīng)用程序你現(xiàn)在已經(jīng)確認(rèn)數(shù)據(jù)庫連接正常工作了,讓我們來創(chuàng)建一個 Django app-一個包含模型,視圖和Django代碼,并且形式為獨(dú)立Python包的完整Django應(yīng)用。在這里要先解釋一些術(shù)語,初學(xué)者可能會混淆它們。 在第二章

20、我們已經(jīng)創(chuàng)建了 project , 那么 project 和 app 之間到底有什么不同呢?它們的區(qū)別就是一個是配置另一個是代碼:一個project包含很多個Django app以及對它們的配置。技術(shù)上,project的作用是提供配置文件,比方說哪里定義數(shù)據(jù)庫連接信息, 安裝的app列表,TEMPLATE_DIRS,等等。一個app是一套Django功能的集合,通常包括模型和視圖,按Python的包結(jié)構(gòu)的方式存在。例如,Django本身內(nèi)建有一些app,例如注釋系統(tǒng)和自動管理界面。app的一個關(guān)鍵點(diǎn)是它們是很容易移植到其他project和被多個project復(fù)用。對于如何架構(gòu)Django代碼并

21、沒有快速成套的規(guī)則。 如果你只是建造一個簡單的Web站點(diǎn),那么可能你只需要一個app就可以了; 但如果是一個包含許多不相關(guān)的模塊的復(fù)雜的網(wǎng)站,例如電子商務(wù)和社區(qū)之類的站點(diǎn),那么你可能需要把這些模塊劃分成不同的app,以便以后復(fù)用。不錯,你可以不用創(chuàng)建app,這一點(diǎn)應(yīng)經(jīng)被我們之前編寫的視圖函數(shù)的例子證明了 。 在那些例子中,我們只是簡單的創(chuàng)建了一個稱為views.py的文件,編寫了一些函數(shù)并在URLconf中設(shè)置了各個函數(shù)的映射。這些情況都不需要使用apps。但是,系統(tǒng)對app有一個約定: 如果你使用了Django的數(shù)據(jù)庫層(模型),你必須創(chuàng)建一個Django app。 模型必須存放在apps中

22、。 因此,為了開始建造我們的模型,我們必須創(chuàng)建一個新的app。在 mysite 項(xiàng)目文件下輸入下面的命令來創(chuàng)建 books app:python manage.py startapp books這個命令并沒有輸出什么,它只在 mysite 的目錄里創(chuàng)建了一個 books 目錄。 讓我們來看看這個目錄的內(nèi)容:books/ _init_.py models.py tests.pyviews.pyadmin.py這個目錄包含了這個app的模型和視圖。使用你最喜歡的文本編輯器查看一下 models.py 和 views.py 文件的內(nèi)容。 它們都是空的,除了 models.py 里有一個 import

23、。這就是你Django app的基礎(chǔ)。在Python代碼里定義模型我們早些時候談到。MTV里的M代表模型。 Django模型是用Python代碼形式表述的數(shù)據(jù)在數(shù)據(jù)庫中的定義。 對數(shù)據(jù)層來說它等同于 CREATE TABLE 語句,只不過執(zhí)行的是Python代碼而不是 SQL,而且還包含了比數(shù)據(jù)庫字段定義更多的含義。 Django用模型在后臺執(zhí)行SQL代碼并把結(jié)果用Python的數(shù)據(jù)結(jié)構(gòu)來描述。 Django也使用模型來呈現(xiàn)SQL無法處理的高級概念。如果你對數(shù)據(jù)庫很熟悉,你可能馬上就會想到,用Python 和 SQL來定義數(shù)據(jù)模型是不是有點(diǎn)多余? Django這樣做是有下面幾個原因的:自身(運(yùn)

24、行時自動識別數(shù)據(jù)庫)會導(dǎo)致過載和有數(shù)據(jù)完整性問題。為了提供方便的數(shù)據(jù)訪問API, Django需要以某種方式知道數(shù)據(jù)庫層內(nèi)部信息,有兩種實(shí)現(xiàn)方式。第一種方式是用Python明確地定義數(shù)據(jù)模型,第二種方式是通過自身來自動偵測識別數(shù)據(jù)模型。第二種方式看起來更清晰,因?yàn)閿?shù)據(jù)表信息只存放在一個地方-數(shù)據(jù)庫里,但是會帶來一些問題。首先,運(yùn)行時掃描數(shù)據(jù)庫會帶來嚴(yán)重的系統(tǒng)過載。如果每個請求都要掃描數(shù)據(jù)庫的表結(jié)構(gòu),或者即便是服務(wù)啟動時做一次都是會帶來不能接受的系統(tǒng)過載。(有人認(rèn)為這個程度的系統(tǒng)過載是可以接受的,而Django開發(fā)者的目標(biāo)是盡可能地降低框架的系統(tǒng)過載)。第二,某些數(shù)據(jù)庫,尤其是老版本的MySQL

25、,并未完整存儲那些精確的自身元數(shù)據(jù)。編寫Python代碼是非常有趣的,保持用Python的方式思考會避免你的大腦在不同領(lǐng)域來回切換。盡可能的保持在單一的編程環(huán)境/思想狀態(tài)下可以幫助你提高生產(chǎn)率。不得不去重復(fù)寫SQL,再寫Python代碼,再寫SQL,會讓你頭都要裂了。把數(shù)據(jù)模型用代碼的方式表述來讓你可以容易對它們進(jìn)行版本控制。這樣,你可以很容易了解數(shù)據(jù)層的變動情況。SQL只能描述特定類型的數(shù)據(jù)字段。例如,大多數(shù)數(shù)據(jù)庫都沒有專用的字段類型來描述Email地址、URL。而用Django的模型可以做到這一點(diǎn)。好處就是高級的數(shù)據(jù)類型帶來更高的效率和更好的代碼復(fù)用。SQL還有在不同數(shù)據(jù)庫平臺的兼容性問題

26、。發(fā)布Web應(yīng)用的時候,使用Python模塊描述數(shù)據(jù)庫結(jié)構(gòu)信息可以避免為MySQL, PostgreSQL, and SQLite編寫不同的CREATETABLE。當(dāng)然,這個方法也有一個缺點(diǎn),就是Python代碼和數(shù)據(jù)庫表的同步問題。 如果你修改了一個Django模型, 你要自己來修改數(shù)據(jù)庫來保證和模型同步。 我們將在稍后講解解決這個問題的幾種策略。最后,我們要提醒你Django提供了實(shí)用工具來從現(xiàn)有的數(shù)據(jù)庫表中自動掃描生成模型。 這對已有的數(shù)據(jù)庫來說是非常快捷有用的。 我們將在第18章中對此進(jìn)行討論。第一個模型在本章和后續(xù)章節(jié)里,我們把注意力放在一個基本的 書籍/作者/出版商 數(shù)據(jù)庫結(jié)構(gòu)上。

27、 我們這樣做是因?yàn)?這是一個眾所周知的例子,很多SQL有關(guān)的書籍也常用這個舉例。 你現(xiàn)在看的這本書也是由作者 創(chuàng)作再由出版商出版的哦!我們來假定下面的這些概念、字段和關(guān)系:§ 一個作者有姓,有名及email地址。§ 出版商有名稱,地址,所在城市、省,國家,網(wǎng)站。§ 書籍有書名和出版日期。 它有一個或多個作者(和作者是多對多的關(guān)聯(lián)關(guān)系many-to-many), 只有一個出版商(和出版商是一對多的關(guān)聯(lián)關(guān)系one-to-many,也被稱作外鍵foreign key)第一步是用Python代碼來描述它們。 打開由 startapp 命令創(chuàng)建的models.py 并輸入下

28、面的內(nèi)容:from django.db import modelsclass Publisher(models.Model):name = models.CharField(max_length=30)address = models.CharField(max_length=50)city = models.CharField(max_length=60) state_province = models.CharField(max_length=30)country = models.CharField(max_length=50)website = models.URLField()cla

29、ss Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40)email = models.EmailField()class Book(models.Model):title = models.CharField(max_length=100)authors = models.ManyToManyField(Author)publisher = models.ForeignKey(Publisher)publication_dat

30、e = models.DateField()讓我們來快速講解一下這些代碼的含義。 首先要注意的是每個數(shù)據(jù)模型都是 django.db.models.Model 的子類。它的父類 Model 包含了所有必要的和數(shù)據(jù)庫交互的方法,并提供了一個簡潔漂亮的定義數(shù)據(jù)庫字段的語法。 信不信由你,這些就是我們需要編寫的通過Django存取基本數(shù)據(jù)的所有代碼。每個模型相當(dāng)于單個數(shù)據(jù)庫表,每個屬性也是這個表中的一個字段。屬性名就是字段名,它的類型(例如 CharField )相當(dāng)于數(shù)據(jù)庫的字段類型 (例如 varchar )。例如, Publisher 模塊等同于下面這張表(用PostgreSQL的 CREAT

31、ETABLE 語法描述):CREATE TABLE "books_publisher" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(30) NOT NULL, "address" varchar(50) NOT NULL, "city" varchar(60) NOT NULL, "state_province" varchar(30) NOT NULL, "country" varchar(50)

32、 NOT NULL, "website" varchar(200) NOT NULL);事實(shí)上,正如過一會兒我們所要展示的,Django 可以自動生成這些 CREATETABLE 語句。“每個數(shù)據(jù)庫表對應(yīng)一個類”這條規(guī)則的例外情況是多對多關(guān)系。 在我們的范例模型中, Book 有一個 多對多字段 叫做 authors。 該字段表明一本書籍有一個或多個作者,但 Book數(shù)據(jù)庫表卻并沒有 authors 字段。相反,Django創(chuàng)建了一個額外的表(多對多連接表)來處理書籍和作者之間的映射關(guān)系。請查看附錄 B 了解所有的字段類型和模型語法選項(xiàng)需要查閱.。最后需要注意的是,我們并沒

33、有顯式地為這些模型定義任何主鍵。除非你單獨(dú)指明,否則Django會自動為每個模型生成一個自增長的整數(shù)主鍵字段每個Django模型都要求有單獨(dú)的主鍵id。模型安裝完成這些代碼之后,現(xiàn)在讓我們來在數(shù)據(jù)庫中創(chuàng)建這些表。 要完成該項(xiàng)工作,第一步是在 Django 項(xiàng)目中 激活 這些模型。 將 books app 添加到配置文件的已安裝應(yīng)用列表中即可完成此步驟。再次編輯 settings.py 文件,找到 INSTALLED_APPS 設(shè)置。INSTALLED_APPS 告訴 Django 項(xiàng)目哪些 app 處于激活狀態(tài)。 缺省情況下如下所示:INSTALLED_APPS = ( 'django

34、.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites',)把這四個設(shè)置前面加#臨時注釋起來。 (這四個app是經(jīng)常使用到的,我們將在后續(xù)章節(jié)里討論如何使用它們)。同時,注釋掉MIDDLEWARE_CLASSES的默認(rèn)設(shè)置條目,因?yàn)檫@些條目是依賴于剛才我們剛在INSTALLED_APPS注釋掉的apps。 然后,添加 mysite.books 到 INSTALLED_APPS 的末尾,此時設(shè)置的內(nèi)容看起來

35、應(yīng)該是這樣的:MIDDLEWARE_CLASSES = ( # 'mon.CommonMiddleware', # 'django.contrib.sessions.middleware.SessionMiddleware', # 'django.contrib.auth.middleware.AuthenticationMiddleware',)INSTALLED_APPS = ( # 'django.contrib.auth', # 'django.contrib.contenttypes', # 'd

36、jango.contrib.sessions', # 'django.contrib.sites', 'books',)(就像我們在上一章設(shè)置TEMPLATE_DIRS所提到的逗號,同樣在INSTALLED_APPS的末尾也需添加一個逗號,因?yàn)檫@是個單元素的元組。另外,本書的作者喜歡在 每一個 tuple元素后面加一個逗號,不管它是不是只有一個元素。這是為了避免忘了加逗號,而且也沒什么壞處。)現(xiàn)在我們可以創(chuàng)建數(shù)據(jù)庫表了。 首先,用下面的命令驗(yàn)證模型的有效性:python manage.py validatevalidate 命令檢查你的模型的語法和邏輯是

37、否正確。 如果一切正常,你會看到 0errorsfound 消息。如果出錯,請檢查你輸入的模型代碼。 錯誤輸出會給出非常有用的錯誤信息來幫助你修正你的模型。一旦你覺得你的模型可能有問題,運(yùn)行 pythonmanage.pyvalidate 。它可以幫助你捕獲一些常見的模型定義錯誤。模型確認(rèn)沒問題了,運(yùn)行下面的命令來生成 CREATETABLE 語句(如果你使用的是Unix,那么可以啟用語法高亮):python manage.py sqlall books在這個命令行中, books 是app的名稱。 和你運(yùn)行 manage.pystartapp 中的一樣。執(zhí)行之后,輸出如下:BEGIN;CRE

38、ATE TABLE "books_publisher" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(30) NOT NULL, "address" varchar(50) NOT NULL, "city" varchar(60) NOT NULL, "state_province" varchar(30) NOT NULL, "country" varchar(50) NOT NULL, "

39、;website" varchar(200) NOT NULL);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);CREATE TABLE "books_book" ( "id&qu

40、ot; serial NOT NULL PRIMARY KEY, "title" varchar(100) NOT NULL, "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id") DEFERRABLE INITIALLY DEFERRED, "publication_date" date NOT NULL);CREATE TABLE "books_book_authors" ( "i

41、d" serial NOT NULL PRIMARY KEY, "book_id" integer NOT NULL REFERENCES "books_book" ("id") DEFERRABLE INITIALLY DEFERRED, "author_id" integer NOT NULL REFERENCES "books_author" ("id") DEFERRABLE INITIALLY DEFERRED, UNIQUE ("book_id

42、", "author_id");CREATE INDEX "books_book_publisher_id" ON "books_book" ("publisher_id");COMMIT;注意:§ 自動生成的表名是app名稱( books )和模型的小寫名稱 ( publisher , book , author )的組合。你可以參考附錄B重寫這個規(guī)則需要查閱。§ 我們前面已經(jīng)提到,Django為每個表格自動添加了一個 id 主鍵,你可以重新設(shè)置它。§ 按約定,Django

43、添加 "_id" 后綴到外鍵字段名。你猜對了,這個同樣是可以自定義的。§ 外鍵是用 REFERENCES 語句明確定義的。§ 這些 CREATETABLE 語句會根據(jù)你的數(shù)據(jù)庫而作調(diào)整,這樣象數(shù)據(jù)庫特定的一些字段例如:(MySQL),auto_increment(PostgreSQL),serial(SQLite),都會自動生成。Integerprimarykey 同樣的,字段名稱也是自動處理(例如單引號還好是雙引號)。例子中的輸出是基于PostgreSQL語法的。sqlall 命令并沒有在數(shù)據(jù)庫中真正創(chuàng)建數(shù)據(jù)表,只是把SQL語句段打印出來,這樣你可以看

44、到Django究竟會做些什么。如果你想這么做的話,你可以把那些SQL語句復(fù)制到你的數(shù)據(jù)庫客戶端執(zhí)行,或者通過Unix管道直接進(jìn)行操作(例如, python manager.py sqlall books | psql mydb )。不過,Django提供了一種更為簡易的提交SQL語句至數(shù)據(jù)庫的方法: syncdb 命令python manage.py syncdb執(zhí)行這個命令后,將看到類似以下的內(nèi)容:Creating table books_publisherCreating table books_authorCreating table books_bookInstalling index

45、 for books.Book modelsyncdb 命令是同步你的模型到數(shù)據(jù)庫的一個簡單方法。 它會根據(jù) INSTALLED_APPS 里設(shè)置的app來檢查數(shù)據(jù)庫, 如果表不存在,它就會創(chuàng)建它。 需要注意的是, syncdb 并 不能將模型的修改或刪除同步到數(shù)據(jù)庫;如果你修改或刪除了一個模型,并想把它提交到數(shù)據(jù)庫,syncdb并不會做出任何處理。 (更多內(nèi)容請查看本章最后的“修改數(shù)據(jù)庫的架構(gòu)”一段。)如果你再次運(yùn)行 pythonmanage.pysyncdb,什么也沒發(fā)生,因?yàn)槟銢]有添加新的模型或者 添加新的app。因此,運(yùn)行pythonmanage.pysyncdb總是安全的,因?yàn)樗粫?/p>

46、重復(fù)執(zhí)行SQL語句。如果你有興趣,花點(diǎn)時間用你的SQL客戶端登錄進(jìn)數(shù)據(jù)庫服務(wù)器看看剛才Django創(chuàng)建的數(shù)據(jù)表。你可以手動啟動命令行客戶端(例如,執(zhí)行PostgreSQL的 psql 命令),也可以執(zhí)行 python manage.py dbshell ,這個命令將依據(jù) DATABASE_SERVER 的里設(shè)置自動檢測使用哪種命令行客戶端。常言說,后來者居上。基本數(shù)據(jù)訪問一旦你創(chuàng)建了模型,Django自動為這些模型提供了高級的Python API。 運(yùn)行 pythonmanage.pyshell 并輸入下面的內(nèi)容試試看:>>>from books.models import

47、Publisher>>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',. city='Berkeley', state_province='CA', country='U.S.A.',. website='>>>p1.save()>>> p2 = Publisher(name="O'Reilly", address='10 Fawcett

48、St.',. city='Cambridge', state_province='MA', country='U.S.A.',. website='>>>p2.save()>>> publisher_list = Publisher.objects.all()>>> publisher_list<Publisher: Publisher object>, <Publisher: Publisher object>這短短幾行代碼干了不少的事。 這里簡單的說

49、一下:§ 首先,導(dǎo)入Publisher模型類, 通過這個類我們可以與包含 出版社 的數(shù)據(jù)表進(jìn)行交互。§ 接著,創(chuàng)建一個 Publisher 類的實(shí)例并設(shè)置了字段 name, address 等的值。§ 調(diào)用該對象的 save() 方法,將對象保存到數(shù)據(jù)庫中。 Django 會在后臺執(zhí)行一條 INSERT 語句。§ 最后,使用 Publisher.objects 屬性從數(shù)據(jù)庫取出出版商的信息,這個屬性可以認(rèn)為是包含出版商的記錄集。 這個屬性有許多方法, 這里先介紹調(diào)用 Publisher.objects.all() 方法獲取數(shù)據(jù)庫中 Publisher 類

50、的所有對象。這個操作的幕后,Django執(zhí)行了一條SQL SELECT 語句。這里有一個值得注意的地方,在這個例子可能并未清晰地展示。當(dāng)你使用Django modle API創(chuàng)建對象時Django并未將對象保存至數(shù)據(jù)庫內(nèi),除非你調(diào)用 save() 方法:p1 = Publisher(.)# At this point, p1 is not saved to the database yet!p1.save()# Now it is.如果需要一步完成對象的創(chuàng)建與存儲至數(shù)據(jù)庫,就使用 objects.create() 方法。 下面的例子與之前的例子等價(jià):>>> p1 = Publ

51、isher.objects.create(name='Apress',. address='2855 Telegraph Avenue',. city='Berkeley', state_province='CA', country='U.S.A.',. website='>>> p2 = Publisher.objects.create(name="O'Reilly",. address='10 Fawcett St.', city='

52、Cambridge',. state_province='MA', country='U.S.A.',. website='>>> publisher_list = Publisher.objects.all()>>> publisher_list當(dāng)然,你肯定想執(zhí)行更多的Django數(shù)據(jù)庫API試試看,不過,還是讓我們先解決一點(diǎn)煩人的小問題。添加模塊的字符串表現(xiàn)當(dāng)我們打印整個publisher列表時,我們沒有得到想要的有用信息,無法把對象區(qū)分開來:System Message: WARNING/2 (<s

53、tring>, line 872); backlinkInline literal start-string without end-string.System Message: WARNING/2 (<string>, line 872); backlinkInline literal start-string without end-string.<Publisher: Publisher object>, <Publisher: Publisher object>我們可以簡單解決這個問題,只需要為Publisher 對象添加一個方法 _unico

54、de_() 。 _unicode_() 方法告訴Python如何將對象以unicode的方式顯示出來。 為以上三個模型添加_unicode_()方法后,就可以看到效果了:from django.db import modelsclass Publisher(models.Model):name = models.CharField(max_length=30)address = models.CharField(max_length=50)city = models.CharField(max_length=60) state_province = models.CharField(max_l

55、ength=30)country = models.CharField(max_length=50)website = models.URLField()def _unicode_(self):return class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40)email = models.EmailField()def _unicode_(self):return u'%s %s'

56、% (self.first_name, self.last_name)class Book(models.Model):title = models.CharField(max_length=100)authors = models.ManyToManyField(Author)publisher = models.ForeignKey(Publisher) publication_date = models.DateField()def _unicode_(self):return self.title就象你看到的一樣, _unicode_() 方法可以進(jìn)行任何處理來返回對一個對象的字符串表

57、示。 Publisher和Book對象的_unicode_()方法簡單地返回各自的名稱和標(biāo)題,Author對象的_unicode_()方法則稍微復(fù)雜一些,它將first_name和last_name字段值以空格連接后再返回。對_unicode_()的唯一要求就是它要返回一個unicode對象,如果 _unicode_() 方法未返回一個Unicode對象,而返回比如說一個整型數(shù)字,那么Python將拋出一個 TypeError 錯誤,并提示:”coercing to Unicode: need string or buffer, int found” 。Unicode對象什么是Unicode對

58、象呢?你可以認(rèn)為unicode對象就是一個Python字符串,它可以處理上百萬不同類別的字符從古老版本的Latin字符到非Latin字符,再到曲折的引用和艱澀的符號。普通的python字符串是經(jīng)過編碼的,意思就是它們使用了某種編碼方式(如ASCII,ISO-8859-1或者UTF-8)來編碼。 如果你把奇特的字符(其它任何超出標(biāo)準(zhǔn)128個如0-9和A-Z之類的ASCII字符)保存在一個普通的Python字符串里,你一定要跟蹤你的字符串是用什么編碼的,否則這些奇特的字符可能會在顯示或者打印的時候出現(xiàn)亂碼。 當(dāng)你嘗試要將用某種編碼保存的數(shù)據(jù)結(jié)合到另外一種編碼的數(shù)據(jù)中,或者你想要把它顯示在已經(jīng)假定了某種編碼的程序中的時候,問題就會發(fā)生。 我們都已經(jīng)見到過網(wǎng)頁和郵件被?弄得亂七八糟。 ? 或者其它出現(xiàn)在奇怪位置的字符:這一般來說就是存在編碼問題了。但是Unicode對象并沒有編碼。它們使用Unicode,一個一致的,通用的字符編碼集。 當(dāng)你在Python中處理

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論