Django是一個Web框架——一套用於幫助開發交互式網站的工具。Django能夠響應網頁請求,還能讓你更輕松地讀寫數據庫、管理用戶等。
1、建立項目
開始編寫一個名為“學習筆記”的Web應用程序,讓用戶能夠記錄感興趣的主題,並在學習每個主題的過程中添加日志條目。“學習筆記”的主頁對這個網站進行描述,並邀請用戶注冊或登錄。用戶登錄后,就可以創建主題、添加新條目以及閱讀既有的條目。
1.安裝Python:Python
2.安裝IDE(我使用的是Pycharm社區版):Pycharm
3.在Pycharm新建項目:
File->New Project,設置如下
4.安裝Django:Django
cmd
進入終端,cd到python安裝的Script文件夾下,利用pip命令安裝Django,或將python安裝目錄Script文件夾路徑加入環境變量中,則可直接使用pip命令。- 使用
pip install django
命令安裝Django
5.在Django中創建項目:
在Pycharm中新建的項目中,利用Terminal終端在虛擬環境下使用django-admin startproject project-name .
創建項目,注意命令后的點號,書上提到,忘記點號在部署應用程序時會遇到一些配置問題。忘記點號,就將創建的目錄文件夾刪除再運行一邊命令
Django在項目中新建了一個名為learnning_log的目錄,其中最重要的是settings.py、urls,py、wsgi.py
- 文件settings.py指定Django如何與你的系統交互以及如何管理項目。在開發過程中我們將修改其中過一些設置,並添加一些設置
- 文件urls.py告訴Django應創建哪些網頁來響應瀏覽器請求
- 文件wsgi.py幫助Django提供它創建的文件,這個文件名是web server gateway interface(Web服務器網關接口)的首字母縮寫
還創建了一個名為manage.py的文件,這是一個簡單的程序,它接受命令並將其交給Django的相關部分去運行。我們將使用這些命令來管理諸如使用數據庫和運行服務器等任務
6.創建數據庫:
使用migrate
命令創建一個供Django使用的數據庫:python manage.py migrate
我們將修改數據庫稱為遷移數據庫。首次執行命令migrate時,將讓Django確保數據庫與項目的當前狀態匹配。在使用SQLite的新項目中首次執行這個命令時,Django將創建一個數據庫
運行過命令后,我們會發現,項目中多出來了一個db.sqlite3文件,SQLite是一種使用單個文件的數據庫,是編寫簡單應用程序的理想選擇,因為它讓你不用太關注數據庫管理的問題
7.查看項目
執行命令runserver,合適Django是否正確地創建了項目:python manage.py runserver
Django啟動一個服務器,讓你能夠查看系統中地項目,了解他們地工作。當瀏覽器中輸入url請求網頁時,該Django服務器將進行響應:生成合適地網頁,並將其發送給瀏覽器
注意 如果出現錯誤消息 “That portis already iin use"(指定端口已被占用),請執行
python manage.py runserver 8001
,讓Django使用另一個端口;如果這個端口也不可用,請不斷執行上述命令,更改其中指定的端口號,直到找到可用的端口。
2、創建應用程序
Django項目由一系列應用程序組成,它們協同工作,讓項目成為一個整體。我接下來創建一個應用程序,他將完成項目的大部分工作。
當前,在前面打開的終端窗口運行着runserver
。我們再打開一個終端窗口,執行命令startapp
命令startapp appname讓Django建立創建應用程序的基礎設施。現在查看項目目錄,新增了一個文件夾learning_logs
該文件夾中最重要的文件是models.py、admin.py、views.py
接下來使用models.py來定義我們在應用程序中管理的數據
1.定義模型:
我們考慮設計的數據。每位用戶在學習筆記中需要創建很多主題。用戶輸入每個條目都與特定主題相關聯,這些條目以文本的形式顯示。我們還需要存儲每個條目的時間戳,以便能夠告訴用戶各個條目都是什么時候創建的
打開models.py,它為我們導入了模塊models,我們還能創建自己的模型。模型告訴Django如何處理應用程序中存儲的數據。現在我們創建一個名為Topic的類,繼承Model,表示用戶將存儲的主題的模型,它包含text和date_added兩個屬性
- 屬性text是一個CharField——由字符或文本組成的數據,我們還設置max_length=200告訴Django在數據庫中主題名應預留多少空間
- 屬性date_added是一個DateTimeField——記錄日期和時間的數據,我們傳遞auto_now_add=True,當用戶創建新主題時,讓Django將該屬性設置成當前日期和時間
- 我們還需要告訴Django,默認使用哪個屬性顯示有關主題的信息。注意:在python2.7中,應調用__ unicode __ ()方法而不是__ str __ ()方法
2.激活模型:
要使用模型,必須讓Django將應用程序包含到項目中,為此應該在settings.py中的INSTALLED_APPS片段中添加我們的應用程序信息
接下來,需要讓Django修改數據庫,使其能夠存儲與模型Topic相關的信息。為此,在終端窗口執行makemigrations
命令讓Django確定該如何修改數據庫,執行后Django將創建一個遷移文件在數據庫中為模型Topic創建一個表
下面,使用migrate
來應用這種遷移,讓Django替我們修改數據庫
3.Django管理網站
為應用程序定義模型時,Django提供的管理網站admin site讓我們能夠輕松地處理模型。接下來,我們就建立管理網站,並通過它使用模型Topic來添加一些主題
創建超級用戶:
執行python manage.py createsuperuser
命令在Django中創建超級用戶,執行命令后,Django提示輸入超級用戶的用戶名(默認)、郵箱(可放空)、密碼、確認密碼
向管理網站注冊模型:
在models.py所在目錄中的admin.py文件中輸入下面代碼向管理網站注冊Topic
from learning_logs.models import Topic
admin site.register(Topic)
現在使用超級用戶賬戶訪問登錄網站:http://localhost:8000/admin/ ,輸入剛創建的超級用戶的用戶名和密碼,進入如下界面(Django administration)。這個網頁能讓我們添加和修改用戶和用戶組,還可以管理剛才定義的模型Topic相關的數據,接下來,我們來添加第一個主題
添加主題:
單擊Topics進入主題網頁,它幾乎是空的,因為我們還沒有添加任何主題
單擊Add,看到一個用於添加新主題的表單,在第一個輸入框中輸Chess,再單擊Save,這將返回主題管理頁面,其中剛創建的主題已被添加,按照該步驟我們再創建一個Rock Climbing主題
4.定義模型Entry:
特定主題下有用戶在學習筆記記錄的知識條目,這是一種多對一關系,即多個知識條目關聯到同一個主題
像Topic一樣,我們創建Entry模型,它繼承Django基類Model,擁有topic、text、date_added三個屬性
- topic屬性:是一個ForeignKey實例,它引用數據庫中的另一條記錄,將每個條目關聯到特定的主題
- text屬性:一個不限制長度的TextField實例
- date_added屬性:條目的時間戳
- Meta類:嵌套的Meta類,用於存儲管理模型的額外信息,在這里我們能夠設置一個特殊屬性,讓Django在需要時使用Entries來表示多個條目。如果沒有這個類,Django將使用Entrys來表示多個條目
- __ unicode __ ()方法:告訴Django,呈現條目時應該顯示那些信息,我們只顯示text的前50個字符,並用...指出顯示內容並非整個條目
遷移模型Entry:
由於我們新添加了一個新模型,因此需要再次遷移數據庫
這個過程是:
- 修改models.py
- 執行命令
python manage.py makemigrations app_name
- 再執行
python manage.py migrate
生成了一個新的遷移文件,告訴Django如何修改數據庫,使其能存儲與模型Entry相關的信息,然后執行migrate,應用遷移
向管理網站注冊Entry:
在admin.py中注冊模型Entry
返回http://localhost:8000/admin/,你將看到learing_logs下列出了Entries,單擊Entries的Add鏈接或單擊Entries再選擇Add entry。
你將看到一個下拉列表,能選擇要創建哪個主題的條目,還有一個輸入條目的文本框。我們添加一個Chess主題的條目,如下:
返回條目管理頁面,我們能看到添加的條目以及使用text[:50]呈現出來的條目信息
3、創建網頁:學習筆記主頁
使用Django創建網頁的過程通常分三個階段:定義URL、編寫視圖和編寫模板。首先,你必須定義URL模式。URL模式描述了URL是如何設計的,讓Django知道如何將瀏覽器請求與網站URL匹配,以確定返回哪個網頁。
每個URL都被映射到特定的視圖——視圖函數獲取並處理網頁所需的數據。視圖函數通常條用一個模板,后者生成瀏覽器能夠理解的網頁。我們接下來創建學習筆記的主頁。我們將定義主頁的URL、編寫其視圖函數並創建一個簡單的模板
鑒於我們只是要確保”學習筆記“按要求的那樣工作,我們將暫時讓這個網頁盡可能簡單。Web應用程序能夠正常運行后,設置樣式可使其更有趣,但中看不中用的應用程序毫無意義。目前的主頁只顯示標題和簡單的描述。
1.映射URL:
用戶通過在瀏覽器中輸入URL以及單擊鏈接來請求網頁,因此我們需要確定項目所需的URL。
當前,基礎URL(http://localhost:8000/ )返回默認的Django網站,讓我們知道正確建立了項目。我們將修改這一點,讓這個基礎URL映射到”學習筆記“的主頁
首先,我們修改項目文件夾中的urls.py
urls.py文件的urlpatterns主體包含了項目中的應用程序的URL。其中的admin.site.urls定義了可在管理網站中請求的所有URL
我們添加了learning_logs.urls並包含namespace將learning_logs的URL同項目中的其他URL區分開來,這在項目擴展時很有幫助
所以我們又需要在文件夾learning_logs中創建另一個urls.py文件:
在應用程序的urls.py中,我們導入了url模塊用於將URL映射到視圖,還導入了views模塊,其中的句點表示讓Python從當前的urls.py模塊所在的文件夾中導入視圖。變量urlpatterns是一個包含了可在應用程序learning_logs中請求的網頁
實際的URL模式是一個對函數url()
的調用,這個函數接受三個實參:
- 第一個是一個正則表達式。例如:
r'^$'
,其中的r
讓Python將接下來的字符串視為原始字符串,引號包括正則表達式的起止。脫字符^
讓Python查看字符串的開頭,美元符$
讓Python查看字符串末尾 - 第二個實參指定了要調用的視圖函數。當請求的URL與前述正則表達式匹配時,Django將調用views.index(視圖編寫在后面)
- 第三個實參將這個URL模式的名稱指定為index,讓我們能夠在代碼的其他地方引用它。當需要提供主頁的鏈接時,都將使用這個名稱,而不用編寫URL
2.編寫視圖:
視圖函數接受請求中的信息,准備好生成網頁所需的數據,再將這些數據發送給服務器
我們在learning_logs應用程序的views.py中為主頁編寫視圖,如下:
URL請求與我們剛才定義的模式匹配時,Django將在文件views.py中查找函數index(),再將請求對象傳遞給這個視圖函數。在這里,我們不用處理任何數據,因此這個函數只調用render(),向它提供兩個實參:原始請求對象以及一個用於創建網頁的模板。接下來就是編寫模板了
3.編寫模板:
模板定義了網頁的結構。模板定義了網頁是什么樣的,每當網頁被請求時,Django將填入相關的數據。模板讓你能夠訪問試圖提供的任何數據。
我們在learning_logs中新建一個文件夾,將其命名為templates,在templates中再創建一個learning_logs文件夾(這似乎有些多余?但建立了Django能夠明確解讀的結構,即使項目很大,包含很多應用程序亦如此)。然后創建index.html文件,編寫index.html代碼
<p>Learning Log</p>
<P>Learning Log helps you keep track of your learning, for any topic you're learning about.</p>
現在,我們再請求項目的基礎URL——http://localhost:8000/ ,將看到剛才創建的網頁,而不是默認的Django網頁。Django接受請求的URL匹配了模式r'^$'
,因此調用函數views.index(),於是使用index.html包含的模板來渲染網頁,結果如下
4、創建其他網頁
制定創建網頁的流程后,可以開始擴充”學習筆記“的項目了。我們將創建兩個顯示數據的網頁,其中一個列出所有的主題,另一個顯示指定主題的所有條目。對於每個網頁我們都將指定URL模式,編寫一個視圖函數,並編寫一個模板。
1.模板繼承:
創建網站時,幾乎都有一些所有網頁都將包含的元素。在這種情況下,可以編寫一個包含通用元素的父模板,並讓每個網頁都繼承這個模板,而不必在每個網頁中重復定義這些通用元素。這種方法讓你能專注於開發每個網頁的獨特方面,還能讓修改項目的整體外觀容易很多
我們在learning_logs/templates/learning_logs下創建我們的模板
創建一個base.html
其中我們使用了模板標簽{% %}
,模板標簽是一小段代碼,生成要在網頁中顯示的信息。這里,模板標簽{% url 'learning_logs:index' %}
生成一個url,該url於learning_logs/urls.py中定義的名為index的URL模式匹配
利用模板標簽來生成URL,有利於更新鏈接。要修改項目中的URL,只需修改urls.py中的URL模式,這樣網頁被請求時,Django自動插入修改后的URL
重寫index.html,使其繼承base.html,如下
標簽{% extends %}
指定繼承的父模板
標簽{% block %}
定義content塊,再使用{% endblock content %}
指定了內容定義的結束位置
這里,模板繼承的優點開始顯現出來了:在子模版中,只需包含當前網頁特有的網內容。
2.顯示所有主題的頁面:
URL模式
這個模式與這樣的URL匹配:基礎URL后面跟着topics,可以在末尾包含斜杠,也可以省略它,但單詞topics后面不能又任何東西,否則就與該模式不匹配。該模式匹配的請求都交給views.py中的函數topics()處理
視圖
導入所需數據相關聯的Topic模型,將Topic對象按屬性date_added排序,存入一個上下文字典中,創建使用數據的網頁時,除對象request和模板的路徑外,我們還將變量context傳遞給render()
模板
與模板index.html類似的,topics.html繼承base.html父模板
我們使用了一個相當於for循環的模板標簽,遍歷字典context中的列表topics,{{ topic }}
是一個模板變量,Django會將這部分替換為topic的當前值
我們還使用了模板標簽{{% empty % }}
告訴Django在topics列表為空的時候怎么辦
現在修改父模板,使其包含到顯示所有主題的頁面的鏈接
到瀏覽器主頁單擊Topics鏈接看到如下網頁
3.顯示特定主題的頁面
URL模式
我們再看看這個URL模式中的正則表達式——r'^topics/(?P<topic_id>\d+)/$'
。r讓Django將這個字符串是為原始字符串,並指出正則表達式包含在引號內。表達式的第二部分(/(?P<topic_id>\d+)/)
與包含在兩個斜杠內的整數匹配,並將這個整數存儲在一個名為topic_id的實參中。這部分表達式兩邊的括號捕獲URL中的值;?P<topic_id>
即將匹配的值存儲在topic_id中;\d+
與包含在兩個斜杠內的任何數字都匹配,不管這個數字多少位
發現URL與這個模式匹配時,Django將調用視圖函數topic(),並將存儲在topic_id中的值作為實參傳遞給它
視圖
topic函數中包含了一個形參,我們使用get()獲取topic_id指定的主題,使用entry_set.order_by()獲取降序排序的條目。這是一種查詢,在自己的項目中編寫類似的查詢時,我們應該使用Django shell先進行嘗試。然后把查詢結果存入字典中發送給模板topic.html
模板
該模板也繼承了base.html父模板
特別的,在該模板中我們使用了模板過濾器|
用一個豎線表示。例如date: 'M d, Y H:i'
以這樣的格式顯示時間戳:January 1,2015 23:00
,過濾器linebreaks
將包含換行符的長條目轉換成瀏覽器能夠理解的格式,以免顯示一個不間斷的文本塊
將顯示所有主題的頁面中的每個主題都設置為鏈接
在topics請求頁面中,鏈接到顯示相應主題的頁面,如http://localhost:8000/topics/1/ ,結果如下