對Django這個
框架
感
興趣
很久了,卻一直懶於
研究
學習
,如今跟隨官網的
教程
跑一遍,學學Django同時也
繼續
學學
Python
。
在開始以前,
咱們
先把Python和Django這個框架安裝好。
官網:
https://www.djangoproject.com/
下載
:http://www.djangoproject.
com
/download/1.3/tarball/
因爲兼容性
問題
,Django並不支持Python3+,只支持版本2.4到2.7,因此若是你的
系統
(本人使用的是SUSE Linux Enterprise Server 10 SP3,如下都是以這個系統爲例)沒有安裝Python,或者版本不
符合
,那麼就先要安裝一個合適的版本,我使用的是2.7.2版本:
2 |
tar jxvf Python-2.7.2. tar .bz2 |
下載完後運行python setup.py install進行安裝:
2 |
tar xzvf Django-1.3. tar .gz |
4 |
python setup.py install |
安裝完成後,
驗證
下是否
成功
,
輸入
python進入命令行,而後輸入以下語句導入django而且輸出django的版本號:
2 |
>>> print django.get_version() |
OK,下面咱們
能夠
正式開始了。 在這個教程裏,咱們會建立一個簡單的投票
應用
。它包括兩部分:
- 一個公共網頁讓人查看投票和進行投票。
- 一個管理網頁讓你添加,修改和刪除投票
獲取幫助:node
若是你對這個教程有任何疑問,請到django-users留言或者在irc.freenode.net上訪問#django,找一些可能爲你提供幫助的Django用戶。python
下面開始
創建
一個項目。首先
cd
到存放項目的目錄,而後運行
django-admin.py startproject mysite
命令建立項目:
2 |
django-admin.py startproject mysite |
執行
完後將會在當前目錄建立一個名爲mysite的項目。
發佈包的文件名可能不一樣mysql
若是你是經過Linux發佈包管理系統(例如apt-get或者yum)安裝Django,django-admin.py可能會被重命名爲django-admin,你能夠忽略命令裏的.py繼續完成這個文檔。sql
Mac OS X權限問題shell
若是你使用的是Mac OS X,當運行django-admin.py startproject的時候可能會看到信息"permission denied"。這是由於像OS X這種基於Unix的系統,一個文件在運行前必須是"executable"的。你能夠打開Terminal.app而且去到django-admin.py被安裝到的目錄,並運行命令chmod +x django-admin.py來解決這個問題。數據庫
注意apache
要避免跟Python和Django組件的命名衝突,避免使用像django和test這樣的命名。django
若是你是經過
python setup.py
安裝Django的話,django-admin.py應該會在你的系統
路徑
下。若是它不在這個路徑上的話,你能夠在
site-packages/django/bin
裏找到它,
site-packages
是你安裝Python的目錄。你能夠考慮把某個路徑軟
連接
到django-admin.py,例如
/usr/local/bin
。
代碼應該放在哪瀏覽器
若是你是PHP出身的話,你大概會把代碼放在Web Server的根目錄下(例如/var/www)。但在Django裏,別這麼幹。把Python代碼放在Web Server的根目錄裏並非一個好主意,由於有被人在網頁上看到代碼的風險。這個不利於安全。安全
把你的代碼放在根目錄外面的地方,例如/home/mycod(我這裏用的目錄是/home/python)。
回到正題,startproject建立的目錄結構以下:
這些文件的用途是:
- __init__.py: 一個空文件讓Python知道這個目錄是一個Python包。(若是你是一個Python初學者,能夠看官方的Python文檔瞭解更多關於包的內容)
- manage.py: 一個命令行工具用於跟項目的各類交互。詳情查看django-admin.py和manage.py這兩個文件。
- settings.py: 當前項目的設置和配置。詳情能夠查看Django settings。
- urls.py: 當前項目的URL定義。詳情能夠查看URL dispatcher。
下面啓動Django development server來檢查下成果。進入項目目錄
mysite
運行命令
python manage.py runserver
:
Django version 1.3, using settings 'mysite.settings' |
Quit the server with CONTROL-C. |
你已經啓動了Django的開發
服務
器,一個用純Python編寫的輕量級Web server。咱們已經把它包含在Django裏,這樣你就能夠進行快速的開發而不須要去配置諸如
apache
這樣的Production服務器,除非你已經準備好要發佈了。
注意不要把這個服務器看成發佈環境用,它是專門在開發環境中使用的。
如今服務已經啓動了,你能夠在
瀏覽器
上訪問http://127.0.0.1:8000/。你將會看到歡迎
頁面
,以下圖:
改變端口
runserver命令的默認端口是8000。
若是你想改變端口,你能夠把它做爲參數傳給命令行,例如,這個命令會在端口8080上啓動服務:
python manage.py runserver 8080 |
若是想改變IP,那麼能夠跟端口一塊兒傳給命令行。若是要監聽全部的公共IP,能夠這樣:
python manage.py runserver 0.0.0.0:8000 |
開發服務器的文檔能夠在runserver裏找到。
如今,
編輯
settings.py
文件。修改DATABASES的
default
項裏下面的值:
- ENGINE:django.db.backends.postgresql_psycopg2或者django.db.backends.mysql和django.db.backends.sqlite3。也支持其餘數據庫。
- NAME:數據庫名。若是使用的是SQLite的話,數據庫則是系統裏的一個文件,因此NAME應該設爲包含這個文件名字的絕對路徑(注意路徑要使用斜槓/,不管在什麼系統上)。這個文件不須要建立,在第一次進行數據庫同步的時候會自動建立這個文件。
- USER:用戶名。使用SQLite的話則不須要。
- PASSWORD:密碼。使用SQLite的話則不須要。
- HOST:主機地址。使用SQLite的話則不須要。若是數據庫安裝在同一臺機器上,也能夠不指定。
若是你對數據庫不太熟悉的話,
建議
你使用SQLite(把
ENGINE
設爲
django.db.backends.sqlite3
)。SQLite已經做爲Python 2.5以上版本的一部分包含在裏面,因此你不須要做任何的安裝。
在編輯
settings.py
的時候,你會注意到文件底部的INSTAL
LED
_APPS配置項。這些變量保存了那些隨着Django實例啓動的Django應用(如下用app表示)的名字。app能夠被使用到多個項目裏,你也能夠把它們打包和發佈出去供其餘人使用。 INSTALLED_APPS默認包含了如下app,這些app所有由Django自帶:
- django.contrib.auth -- 一個認證系統。
- django.contrib.contenttypes -- 內容類型框架。
- django.contrib.sessions -- session框架。
- django.contrib.sites -- 多網站管理框架。
- django.contrib.messages -- 消息管理框架。
- django.contrib.staticfiles -- 靜態文件管理框架。
爲了方便使用,這些一般
網站
都會用到的應用已經默認包含在項目裏。 這些app每一個都至少要用到一個以上的數據庫表,因此在使用這些應用前咱們先要建立這些表。運行一下命令:
syncdb命令會根據
settings.py
文件裏的INSTALLED_APPS設置建立必需的數據表。你會看到建立表的信息以及會提示你爲認證系統建立超級用戶,跟着提示作就好了。
簡化
就像咱們上面說的,基於常理,默認的那些應用會被自動包含,可是並非全部人都會用到它們。因此若是你不須要用到這些應用,你能夠在執行syncdb命令前隨意把它們在INSTALLED_APPS裏註釋掉或者刪掉。syncdb只會爲INSTALLED_APPS裏的應用建立表。
建立模型
如今環境已經搭好了,能夠正式開工了。
在Django裏,你寫的每一個應用都包含一個Python的包,這個包會根據一個特定的約定放在Python path裏。Django會自動爲每一個app建立一些
基本
的目錄結構,因此你能夠專心寫代碼而沒必要在建立目錄上費心。
Projects vs. apps
項目跟app有什麼不一樣呢?app是一個實現某個功能的網頁應用,例如一個網頁日誌系統,一個公共數據數據庫或者一個簡單的投票應用。而一個項目則是由一堆配置和應用組成的網頁。一個項目能夠包含多個應用,而一個應用可使用在多個項目裏。
你的應用能夠存放在Python path上的任何地方。簡單起見,咱們在
mysite
目錄裏建立一個投票應用。確認你的當前目錄爲
mysite
,並輸入命令:
python manage.py startapp polls |
這樣會建立一個目錄polls,以下:
這個目錄結構將會存放這個poll應用。
在Django裏寫一個有數據庫操做的網頁應用第一步要作的就是定義模型(Model),模型實質上就是附帶元數據的數據層(database layout)。
原理(Philosophy)
模型是跟你的數據相關的一個單一和明確的數據源。它包含了你所儲存的數據的一些必要字段和行爲。Django遵循DRY原則,目的是在一個地方定義你的數據模型而後根據它自動派生出其餘的東西。
在咱們這個簡單的投票應用裏,咱們建立了兩個模型:polls和choices。一個poll包含有一個問題和一個發表日期。一個choice有兩個字段:選項
文字
和投票計數。每個choice都跟一個poll關聯。
這個概念將由一個簡單的Python類來實現。編輯文件
polls/models.py
:
1 |
from django.db import models |
2 |
class Poll(models.Model): |
3 |
question = models.CharField(max_length = 200 ) |
4 |
pub_date = models.DateTimeField( 'date published' ) |
5 |
class Choice(models.Model): |
6 |
poll = models.ForeignKey(Poll) |
7 |
choice = models.CharField(max_length = 200 ) |
8 |
votes = models.IntegerField() |
代碼很直白。每一個模型都由一個django.db.models.Model的子類實現。每一個模型包含一些變量,每一個變量對應一個數據庫裏的字段。
每一個字段由類Field的一個實例表示,例如字符類型的字段由CharField實現,
時間
類型的字段則由DateTimeField實現,這樣Django就知道每一個字段保存的是什麼類型的數據了。
每一個Field實例的名字(例如
question
和
pub_date
)都是機器友好格式的字段名。這些字段會用在你的Python代碼裏,而數據庫則會把它用做字段名。
你能夠在Field的第一個參數指定一個可讀的名字,這個名字會用在Django內部多個地方。若是沒有指定這個名字,Django會使用機器可讀的名字。在這個例子裏,咱們只爲
Poll.pub_date
定義了人可讀的名字,模型裏其餘全部的字段,機器可讀名字已經可做爲人可讀名字。
一些Field類有必須含有的元素,例如CharField,必須給它指定
max_length
。這個不只會用在數據庫schema裏,也會用在數據驗證裏,咱們很快會看到。
最後,注意到用ForeignKey定義了一個
關係
。它告訴Django每一個Choice會關聯到一個Poll。Django支持全部的
經常使用
數據庫關係:多對已,多對多和一對一。
激活模型
Django經過模型裏的那點代碼獲取到了不少的信息,經過這些信息,Django能夠:
- 爲應用建立數據庫模式(CREATE TABLE語句) 。
- 建立訪問Poll和Choice對象的Python數據庫訪問API。
可是首先咱們先要讓咱們的項目知道
polls
這個應用已經安裝。
原理(Philosophy)
Django應用是「可插拔式」的:你能夠把一個應用用在多個項目裏,也能夠把它發佈出去,由於它們不是跟Django的安裝綁定的。
再次編輯文件
settings.py
,修改設置INSTALLED_APPS包含字符串
'polls'
。修改後的配置以下:
'django.contrib.contenttypes', |
'django.contrib.sessions', |
如今Django知道要去包含
polls
這個應用了。咱們執行
另外
一個命令:
python manage.py sql polls |
你應該會看到相似下面的東西(poll應用的
CREATE TABLE
SQL語句):
CREATE TABLE "polls_poll" ( |
"id" integer NOT NULL PRIMARY KEY, |
"question" varchar(200) NOT NULL, |
"pub_date" datetime NOT NULL |
CREATE TABLE "polls_choice" ( |
"id" integer NOT NULL PRIMARY KEY, |
"poll_id" integer NOT NULL REFERENCES "polls_poll" ( "id" ), |
"choice" varchar(200) NOT NULL, |
注意如下幾點:
- 實際輸出的東西會根據你所使用的數據庫而不一樣。
- 表名由應用的名稱(polls)和小寫的模型名稱 —— poll和choice組合而成並自動生成。(你能夠重寫這個規則。)
- 主鍵(IDs)會被自動添加。(一樣能能夠重寫它)
- 爲了方便,Django會添加"_id"到外鍵的字段名上。對的,你一樣能夠重寫它。
- 外鍵關係由一個REFERENCES語句明確肯定。
- 它是爲你所使用的數據庫量身定製的,因此數據庫特有的字段如auto_increment (MySQL),serial (PostgreSQL)或者integer primary key (SQLite)都會自動幫你處理,一樣字段名的引號也是如此,例如,是使用雙引號仍是單引號。這篇教程的做者使用PostgreSQL,因此例子裏的輸出都是PostgreSQL語法。
- sql命令並不會在你的數據庫裏執行SQL語句,它只是在屏幕上顯示給你看Django認爲須要執行哪些SQL語句。若是你想的話,能夠複製和粘貼這些SQL語句到你的數據庫命令行。可是,咱們很快就能看到,Django提供了一個更爲簡單的方式去執行這些SQL到數據庫上。
若是你有興趣,能夠運行如下的命令:
- python manage.py validate -- 檢查模型的結構錯誤。
- python manage.py sqlcustom polls -- 輸出全部爲應用定義的自定義SQL語句 (例如表修改和約束)。
- python manage.py sqlclear polls -- 根據已存在的表,輸出這個應用中必要的DROP TABLE語句。
- python manage.py sqlindexes polls -- 輸出這個應用CREATE INDEX語句。
- python manage.py sqlall polls -- sql,sqlcustom和sqlindexes命令產生的SQL語句的結合。
看這些命令的輸出能夠幫助你更好的
理解
底層發生的事情。
如今,再次運行syncdb在數據庫上建立這些模型的表:
syncdb命令會爲在INSTALLED_APPS裏沒有相應數據表的應用運行'sqlall'產生的sql語句。它會爲自上次運行syncdb以來新添加的應用創建全部的表,初始化數據和
索引
。你能夠在任什麼時候候執行syncdb,它只會建立不存在的表。
閱讀django-admin.py documentation以獲取
manage.py
這個工具所能作的事情的全部信息。
使用API
如今,咱們進入Python的交互
shell
並使用Django提供的API。要進入Python shell,使用這個命令:
我在這裏遇到了ImportError: No module named readline這個錯誤,
解決方法
是下載readline,編譯安裝,而後從新編譯和安裝python就能夠解決這個問題。
咱們使用這個而不是簡單的輸入"python",是由於
manage.py
會幫你建立項目的環境。「建立項目環境」包括兩件事:
- 把polls添加到sys.path裏。爲了靈活性,Django中的模塊經過加點的路徑來引用(例如'polls.models')。爲了實現這個,polls包必須在sys.path裏。
咱們已經遇到過一個這樣的例子了:the INSTALLED_APPS設置裏的列表就是使用點路徑表示法。
- 設置DJANGO_SETTINGS_MODULE環境變量,爲Django指定了你的settings.py文件的路徑。
省略manage.py
若是你不想使用manage.py,沒問題,只須要確保mysite和polls 位於Python路徑的根目錄 (例如import mysite和import polls能正常工做)以及把DJANGO_SETTINGS_MODULE這個環境變量設置到mysite.settings裏。
更多的信息能夠查看django-admin.py documentation.
在shell裏面時,能夠
探索
下database API:
>>> from polls.models import Poll, Choice # 導入咱們剛寫的模型。 |
>>> p = Poll(question = "What's up?" , pub_date = datetime.datetime.now()) |
# 把對象保存進數據庫裏。你須要明確調用save()。 |
# 如今它有個ID了。注意這裏也可能顯示1L而不是1, |
# 取決於你使用的是什麼數據庫。不過這沒什麼打不了, |
# 它只是代表數據庫更傾向於把整型返回成Python的長整型對象。 |
datetime.datetime( 2007 , 7 , 15 , 12 , 00 , 53 ) |
>>> p.pub_date = datetime.datetime( 2007 , 4 , 1 , 0 , 0 ) |
# objects.all()顯示數據庫全部的poll。 |
等等。
<Poll: Poll object>
徹底不能表現出這個對象的
有用信息
。咱們能夠編輯poll模型(在文件
polls/models.py
裏)添加一個__unicode__()
方法
給
Poll
和
Choice
來解決這個問題:
class Poll(models.Model): |
class Choice(models.Model): |
爲你的模型添加__unicode__()方法是頗有必要的。不只是爲了讓你本身更好理解交互提示,並且由於對象的表現的使用會貫穿於整個Django自動產生的admin。
爲何是__unicode__()而不是__str__()?
若是你熟悉Python的話,你可能會更喜歡在你的類裏添加__str__()而不是__unicode__()方法。咱們這裏使用__unicode__()是由於Django模型默認使用Unicode,全部保存在數據庫的數據在返回的時候都會轉化成Unicode。
Django模型有一個默認的__str__()方法叫__unicode__(),它會把結果集轉化成UTF-8字節字符串。在各個意味着unicode(p)會返回一個Unicode字符串,而str(p)會返回一個普通的UTF-8編碼的字符串。
若是你仍是以爲莫名其妙的話,記得把__unicode__()方法加進你的模型中就好了,幸運的話,一切都會如你所想工做。
注意這些都是普通的Python方法,讓咱們添加一個自定義的方法,用做示範:
class Poll(models.Model): |
def was_published_today( self ): |
return self .pub_date.date() = = datetime.date.today() |
添加
import datetime
會引用Python的
datetime
模塊。 保存這些修改而後再次運行
python manage.py shell
新開一個Python交互shell:
>>> from polls.models import Poll, Choice |
# 確保咱們新加的__unicode__()正常工做。 |
>>> Poll.objects. filter ( id = 1 ) |
>>> Poll.objects. filter (question__startswith = 'What' ) |
>>> Poll.objects.get(pub_date__year = 2007 ) |
>>> Poll.objects.get( id = 2 ) |
Traceback (most recent call last): |
DoesNotExist: Poll matching query does not exist. |
# 因此Django爲這種查找方法提供一個便捷的方式。 |
# 下面至關於Poll.objects.get(id=1)。 |
>>> Poll.objects.get(pk = 1 ) |
>>> p = Poll.objects.get(pk = 1 ) |
>>> p.was_published_today() |
# 調用建立函數建立choice對象,會調用INSERT語句, |
# 把choice添加到已存choice的集合裏,並返回這個新建立的Choice對象。 |
# Django會建立一個集合保存外鍵關聯,這個集合能夠經過API進行訪問。 |
>>> p = Poll.objects.get(pk = 1 ) |
>>> p.choice_set.create(choice = 'Not much' , votes = 0 ) |
>>> p.choice_set.create(choice = 'The sky' , votes = 0 ) |
>>> c = p.choice_set.create(choice = 'Just hacking again' , votes = 0 ) |
# Choice對象可經過API訪問它關聯的Poll對象。 |
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] |
# 查找pub_date在2007年的poll的全部choice。 |
>>> Choice.objects. filter (poll__pub_date__year = 2007 ) |
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] |
# 咱們使用delete()刪除一個choice。 |
>>> c = p.choice_set. filter (choice__startswith = 'Just hacking' ) |
更多關於模型關係的信息,能夠看Accessing
related
objects。想知道更多關於如何使用雙下劃線經過API實現字段的查找,看Field lookups。要獲取數據庫API的全部信息,請看Database API reference。
好吧,開篇就到這裏,更詳細請查看:
https://docs.djangoproject.com/en/dev/intro/tutorial01/
Written by icyfire @ 2011.08.05 updated @ 2011.10.09