[譯]正確開始一個Django 1.4項目

原文:Start a Django 1.4 Project the Right Way

開始一個項目時是一個具備決定性做用的階段。所作的每個決定都會對項目產生長遠的影響。雖然有不少關於如何開始一個基於Django框架項目的教程,可是不多有討論怎麼使用專業的、業內已經造成共識的最佳實踐方法來使用Django,保證項目在開發過程當中平衡的成長的。一些不多的計劃可讓你將來的生活變得輕鬆。node

當你讀完這篇文章,你將會得到:
1. 一個功能完備的Django 1.4項目
2. 使用版本控制管理全部的文檔(使用git或者Mercurial)
3. 自動的回退和單元測試(使用unittest library)
4. 一個安裝了你項目的獨立環境(使用virtualenv)
5. 自動的部署和測試(使用Fabric)
6. 自動的數據庫遷移(使用South)
7. 一個均衡你網站的工做流python

全部的這些(也許除了第一點),在官方教程中都沒有說明。他們應該有的。若是你正在想着開始一個新的,可以投入生產的Django 1.4項目,趕忙讀下去吧。git

預備知識

假定你擁有Python的實戰經驗,一樣,若是你以前擁有關於Django的一些使用經驗將會很是有幫助,可是這不是必需的。你須要git(注:有牆)或者Mercurial用做版本控制。就是這些!github

準備開始安裝

我假定你已經安裝好了Python。若是你沒有,能夠先去python.org,找到關於你所用系統的安裝說明。我將會使用託管在Linode的一個64位的Ubuntu server。web

那麼,第一步是什麼呢?安裝Django,是嗎?不徹底是這樣。若是直接在你當前site-packages內安裝包的話,一旦在你的機器中有多個不是Django的基於Python的項目,你也許會陷入項目和安裝的包之間的依賴問題。基於此,咱們將會使用virtualenv和它很是棒的擴展virtualenvwrapper來管理咱們的Django。這對於Django和Python用戶是很是常見和值得推薦的方法。正則表達式

若是你使用pip來安裝包(我想不出任何你不用它的理由),你只需很是簡單的安裝virtualenvwrapper,它會自動安裝virtualenv。shell

$ pip install virtualenvwrapper

安裝好以後,將下面幾行代碼添加進你shell的自啓動文件(.zshrc,.bashrc,.profile,etc)。數據庫

export WORKON_HOME=$HOME/.virtualenvs  
export PROJECT_HOME=$HOME/directory-yo-do-development-in  
source /usr/local/bin/virtualenvwrapper .sh

從新載入你的自啓動文件(e.g. source .zshrc),這樣你就能夠繼續啦。django

建立一個新的環境

建立一個新的虛擬環境很是的簡單。只須要輸入命令:vim

$ mkvirtualenv django_project

這裏"django_project"是任何一個你想要的給項目取的名字。

你將會發現立刻發生了一些事情:你的shell的提示符前加上了"django_project",pip也被自動安裝上了。

這是virtualenvwrapper很是有幫助的地方:在它爲你建立好虛擬環境以後能立刻讓你使用pip來安裝包。命令行提示符前加上了"django_project"是提示你正在使用的是虛擬環境,而不是你係統的Python環境。想要退出虛擬環境很是簡單,輸入命令deactivate便可。當你想要從新回到項目的虛擬環境,只須要輸入workon django_project。注意:在任何路徑下均可以使用這些命令,這與virtualenv不同。

安裝Django

"等一下,安裝Django?我已經安裝好Django了!"奇怪的是,你將不會用到你如今系統中已經安裝好的。咱們將會用一個使用virtualenv管理的Django,它不會將其餘用戶(或者你本身)在機器上其餘地方所使用到的Django弄得混亂。安裝一個虛擬環境下的Django,只須要輸入命令:

$ pip install Django

這將在你的虛擬環境中安裝一個最新版本的Django。你可使用如下命令進行確認:

$ which django-admin.py

這將指向你的$HOME/.virtualenvs/目錄。若是沒有看到這樣的結果,請確認你的命令提示符前有"django_project"。若是沒有,使用workon django_project激活你的虛擬環境。

項目設置

在實際開始項目以前,咱們還須要討論一些小事情。在過去的幾個月,我跟不少Django新手都說過,這些新手有一個最大的不一樣之處就是不使用版本控制系統。許多新手沒有接觸過版本控制,其餘的則是認爲"這是個小項目"不須要版本控制。.

只有使用了版本控制系統纔不會在將來付出沉重的代價。

之前,關於(D)VCS我只說過git。然而,這是個基於Python的項目,Mercurial也是一個很是有價值的選擇。在網上他們都很是的流行,有着大量的資料。確認你已經安裝了git或者Mercurial。他們基本都能經過你的包控制系統(package control system)安裝。

若是你準備使用git,顯然GitHub是你進行代碼託管的選擇。對於Mercurial,Atlassian的Bitbucket是一個好選擇(它也支持git,因此兩種狀況你均可以使用它)。

(source)控制你的環境

雖然到如今咱們尚未作任何事情,咱們知道咱們想讓一切都進行版本控制。咱們有兩類"東西"要提交:咱們的代碼(包括templates,etc)和像數據庫管理,South遷移文件(後面詳述),requirements文件等文件。在過去的文章中,我推薦提交你實際的virtualenv環境,可是有一些很好的理由不去這麼作,至少這不是必需的。使用requirements文件可讓你不須要保存全部的環境。

咱們繼續,如今開始建立咱們的項目目錄。使用新django-admin.pystartproject命令來建立項目。

$ django-damin.py startproject django_project

咱們將會看到建立了一個django_project目錄,在django_project目錄裏,有另外一個包含了settings.py,urls,pywsgi.pydjango_project目錄,還有一個manage.py文件。

插曲:Project vs. Apps

你也許想知道爲何除了已經存在的startapp命令以外添加了新的startproject命令。答案就在於Django的"projects"和"apps"的不一樣,在Django 1.4中有描述。簡單的說,"project"是一個完整的網站或者應用。"app"是一個小的,(最好是)獨立的Django應用,它能夠用在任何Django項目中。好比你要建立一個叫作"Super Blogger"的博客應用,那麼"Super Blogger"就是你的Django project。若是"Super Blogger"支持讀者進行投票,那麼"polls"就是"Super Blogger"使用的一個Django app。主要在於你的"polls"這個"app"能夠被其餘須要投票功能的Django項目進行重用,而不是隻能在"Super Blogger"中使用。一個project是使用各自特有的邏輯將apps組合起來,而app可被用於多個project。

若是你的"Super Blogger"中有不少特殊的邏輯和信息在"polls"這個app中,避免這個有不少好處。基於鬆耦合法則,編寫獨立完整的app可以避免你項目中設計上的決定和bugs直接影響你的app。這也意味着你能夠將一些app的開發給其餘的開發者去作而不須要他們進入或者修改你的主項目。

像不少軟件工程中的法則同樣,這隻須要多作一點點卻能在之後帶來很大的好處。

設置repos

因爲如今在項目中已經有了一些代碼(事實上只有一些腳本和空的配置文件),如今是初始化咱們的repositors的好時機。下面是使用git和Mercurial的步驟。

git

$ git init

這建立了一個git版本庫在當前的目錄。如今讓全部文件保存進git用於提交。

$ git add django_project

如今將他們提交進新的版本庫:

$ git commit -m 'Initial commit of django_project'

Mercurial

$ hg init

這建立了一個Mercurial版本庫在當前目錄。如今將全部文件保存進Mercurial用於提交。

$ hg add django_project

如今將他們提交進新的代碼庫:

$ hg commit -m 'Initial commit of django_project'

若是你準備使用GitHub或者Bitbucket的服務,如今能夠push他們了。

使用South用於數據庫遷移

一個Django中最讓人蛋疼的事情就是models改動以後怎麼同步的數據庫了。在South的幫助下,你只須要建立一個獨立的應用而不須要任何關於數據庫的特殊代碼,models的變更就能被監測到而且使用South建立的migration file能夠自動同步到數據庫。它能讓你同步新的數據結構變更,也能回退來撤銷一個或者一系列改動。它讓你的變得如此輕鬆,很奇怪爲何它沒有被Django收錄(有一些傳言說Django中將會包含一些數據庫遷移的工具,但到目前尚未)。

仍然是在咱們的虛擬環境中,安裝South:

$ pip install south

啓用South須要將它添加進settings.py的INSTALLED_APPS中。如今添加它,同時設置好項目的數據庫,而後運行python manage.py syncdb。你會被提示建立一個超級用戶的用戶名和密碼。更重要的是,South已經設置好了它須要的數據表。

你也許注意到了剛纔咱們只是運行了syncdb而沒有添加任何這這個項目的app。咱們先作這個是由於South須要在最開始就被安裝,咱們全部apps的數據庫遷移將會使用South來操做,包括數據的初始化。

因爲咱們剛作了至關大的變化,如今也是一個提交代碼的時候。你應該養成頻繁提交代碼的習慣,由於你提交的越頻繁,當出錯的時候你選擇回退點的時候會更遊刃有餘。

在提交的時候,讓咱們看看都發生了哪些改變。

(git)

$ git status    
# On branch master  
# Changes not staged for commit:  
#   (use "git add <file>..." to update what will be committed)  
#   (use "git checkout -- <file>..." to discard changes in working directory)  
#  
#       modified:   django_project/settings.py  
#  
# Untracked files:  
#   (use "git add <file>..." to include in what will be committed)  
#  
#       django_project/.settings.py.swp  
#       django_project/__init__.pyc  
#       django_project/settings.pyc

(Mercurial)

$ hg status  
M django_project/django_project/settings.py    
? django_project/django_project/.settings.py.swp  
? django_project/django_project/__init__.pyc  
? django_project/django_project/settings.pyc

在git和Mercurial中,也許你都發現了有一些文件咱們是不想提交的,好比上面的Python的編譯後文件.pyc和vim的臨時文件.swp等。想要忽略這些文件須要建立.gitignore或者hgignore,放在項目的根目錄下,而後按照shell的正則表達式寫入匹配這些你想忽略的文件。舉個例子,個人ignore文件內容以下:

*.pyc  
.*swp

在提交以前,咱們還有一點信息須要去追蹤:咱們所安裝Python包。咱們想追蹤他們的名稱和版本以便於咱們在生產中無縫地建立咱們的環境。幸運的是,pip有一個命令能夠徹底知足咱們這個需求。

$ pip freeze > requirements.txt

我將這些經過管道輸出到一個叫作requirements.txt的文件中,將它加進版本控制中以便於咱們常常性地更新這個列表。

settings.pyrequirements.txt提交:

$ (git/hg) add django_project/settings.py requirements.txt  
$ (git/hg) commit -m 'Added South for database migrations'

建立咱們的APP

用通常的方法使用manage.py建立一個app(python manage.py startapp myapp),而後將其添加進settings.py中的INSTALLED_APP。在添加models以前咱們須要作的事情是告訴South咱們想要用它來作數據遷移:

$ python manage.py schemamigration myapp --initial

這行命令建立了一個數據遷移的文件,咱們能夠用它來同步數據結構的變化(若是有數據表的話),也能夠用來進行回退。咱們這樣使用這個文件來經過數據庫變化(即便是空的):

$ python manage.py migrate myapp

South很是的智能化,知道從哪裏找遷移文件(migration file),同時也記下了咱們的上一次數據庫遷移操做。你能設定獨立的遷移文件,可是通常咱們不須要這麼作。

當咱們最終改動了model,咱們能夠這樣讓South建立一次數據遷移:

$ python manage.py schemamigration myapp --auto

這將檢查myapp中的models,而後自動地對數據庫進行相應的添加、刪除和修改。這些改動可使用上面一樣的命令同步到數據庫。

咱們的開發目錄

一個你須要養成的習慣是要在一個與你線上文件隔離的目錄中進行開發,緣由是顯而易見的。git和Mercurial能讓這變得簡單而且對咱們的部署也有幫助。在你部署django_project的其餘地方建立一個目錄做爲你的開發目錄(我通常命名爲dev)。

在你的開發目錄中,使用git和Mercurial將你的當前項目clone過來:

$ (git/hg) clone /path/to/my/project/

這兩個工具都會準確的將項目拷貝過來,包括全部的改動、分支(branches)和歷史記錄。從如今起,你應該在你的開發目錄中工做。

因爲git和Mercurial的分支使用起來都很是的簡便,當你的開發與你的線上項目有交叉的時候,能夠建立一個分支。使用下面的分別是兩種版本控制系統的操做方法:

(git)

$ git checkout -b <branchname>

這將建立一個已經命名了的分支,同時切換到該分支上。你所作的全部開發基本都應該在一個分支上進行,這樣主分支(master)就能做爲生產環境下主分支(master)的一個備份,任何你想恢復的時候都可以使用它。

(Mercurial)

$ hg branch <branchname>

注意,在Mercurial社區中分支是一個存在爭議的話題,雖然有不少有用的選擇,可是沒有一個「顯然正確」的答案。在這裏,我使用一個命名了的分支,這是最安全和有用的建立分支的風格。在這個分支下所作的一切提交都只在這個分支有效。

使用Fabric來部署

如今咱們作好了一個Django應用,該怎麼部署它呢?Fabric。對於一個規模合理的項目來講,討論其餘的都是浪費時間。Fabric有不少的用途,但在項目部署上是一個亮點。

$ pip install fabric

Fabric須要一個命名爲fabfile.py的文件fabfile,它定義了全部咱們能作的操做。如今開始,在fibfile.py中寫入以下內容,而後放在項目的根目錄下。

from fabric.api import local  
def prepare_development(brance_name):
    local('python manage.py test django_project')  
    local('git add -p && git commit') # or local('hg add && hg commit)

上面的代碼會運行測試代碼而後提交變動,可是僅在經過了你的測試代碼的狀況下。這時候,當你在生產環境下作"pull"操做的時候就變做了一次部署。讓咱們爲實際部署時的文件多添加一些代碼:

from fabric.api import lcd, local  
def deploy():  
with lcd('/path/to/my/prod/area/'):  
    # with git…  
    local('git pull /my/path/to/dev/area/')
    # with Mercurial  
    local('hg pull /my/path/to/dev/area/')  
    local('hg update')  
    # with both  
    local('python manage.py migrate myapp')  
    local('python manage.py test myapp')  
    local('/my/command/to/restart/webserver')

上面的代碼將從你開發環境下的主分支拉取代碼,運行一些數據庫遷移文件,運行你的測試代碼,而後重啓web服務器。全部的這些在終端中一行命令就可以搞定。一旦這些步驟中某一步出錯,這個腳本就會中止執行而且給出提示信息。一旦你修復好,不須要手動運行這些步驟。你能夠簡單的從新運行部署命令,一切就都好了。

注意:上面這些代碼是假定你的開發環境和部署環境是在同一臺機器上的,若是不是這樣,代碼大部分也是相同的,可是須要使用Fabric的run方法代替local。具體能夠閱讀Fabric的文檔

如今咱們建立好了fabfile.py,該怎麼部署呢?簡單,只須要運行:

$ fab prepare_deployment  
$ fab deploy

從技術上來講,這兩個命令能夠合二爲一,可是我發現將準備部署和實際部署操做分開能讓你更加理解你到底在作什麼。

相關文章
相關標籤/搜索