以正確的方式開始一個 Django 1.4 專案

oschina發表於2013-09-15

  早在二月份時,我寫了一篇題為‘開始Django專案的正確方式’的文章,八個月後它仍然吸引了一批受眾。在這八個月,Django框架已經發布到1.4版,活躍發展及前瞻性的1.5版實驗性地支援Python 3.X。伴隨這些變化以及新的、可更新的可供Django開發者使用的可用資源的出現,我決定重新審視一下Django專案最佳實踐的概念。

  專案開始時是一個關鍵時刻,選擇會對專案產生長期的影響。有很多關於如何開始使用Django框架的教程,但很少討論如何專業地使用Django,或如何使用行業公認的最佳做法來確保你的專案規模的持續增長。事前的籌劃讓你走向將來時更容易。

  文章結束時,你將有

  1. 一個全功能的Django 1.4專案
  2. 原始碼受控的所有資源(使用Git或Mercurial)
  3. 自動迴歸和單元測試(使用unittest庫)
  4. 一個獨立於特定環境的安裝專案(使用virtualenv)
  5. 自動化的部署和測試(使用Fabric)
  6. 自動資料庫遷移 (使用South)
  7. 一個標度你站點的開發工作流程

  除了第一部在官方教程內其他部分都不在。它們應該不在。如果你想開始一個新的、生產就緒的Django 1.4專案,請繼續往下看。

  先決條件

  假定你已瞭解Python的基本知識,同時,以往的一些Django經驗會有幫助,但這不是必要的。你需要gitMercurial來進行版本控制。就這些!

  安裝準備

  我假設你已經安裝了Python。如果你沒有的話到python.org找到與你係統架構相符的版本下載安裝。我使用一個Linode上的64位的Ubuntu伺服器,我很高興使用Linode的服務。

  那麼,第一步是什麼呢?安裝Django?不完全是。將安裝包直接安裝到你當前的site-packages裡有一個常見的問題:如果你的機器上有一個以上的Python專案使用Django等其他庫,你可能會碰到應用和安裝軟體庫之間依賴性的問題。因此,我們將使用virtualenv和它的延展virtualenvwrapper來管理我們的Django安裝。這是Python和Django使用者的實踐建議。

  如果你使用pip來安裝第三方庫(我不明白你為什麼不),你可以通過簡單的操作安裝virtualenv和virtualenvwrapper。

$ pip install virtualenvwrapper

  安裝完後,將下附內容新增到你的shell啟動配置檔案中(.zshrc、.bashrc、.profile等)

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

  過載一下你的啟動配置檔案(source .zshrc),現在你已經就緒了。

  建立一個新環境

  建立一個虛擬環境很簡單,只需輸入

$ mkvirtualenv django_project

“django_project”是你的專案的命名。

  你會注意到立馬發生的一些事情:你的shell前面加上了”(django_project)”,distribute和pip被自動安裝了。

  這裡是virtualenvwrapper的一個很有用的部分:它會自動為你準備好環境,讓你馬上可以使用pip安裝庫。“(django_project)”的部分是提醒你正在使用的是virtualenv而不是你係統上的Python。要退出虛擬環境只需簡單輸入deactivate即可。當你要回到你的專案開始工作時,只需使用workon django_project即可。需要注意的是這與vanilla virtualenv工具不同,在哪裡執行這些命令都可以。

  安裝Django

  “等一下,‘安裝Django’?我已經安裝Django了!”,太好了。不過你不會用它的。相反,我們將使用機器上的一個被virtualenv管理的且不會被其他使用者(或你自己)弄亂的Django安裝。在virtualenv中安裝Django,只需輸入:

$ pip install django

  這樣最新版的Django將被安裝在你的virtualenv環境裡,你可以這樣確認:

$ which django-admin.py

  這會指出你的$HOME/.virtualenvs/目錄。如果沒有的話,確認你的輸入提示裡有“(django_project)”。如果沒有,使用workon django_project啟用virtualenv。

  建立專案

  在正式開始專案之前,我們需要認真談一談。在過去的幾個月裡,我對很多Django開發者說過,開發困難的是那些不使用版本控制系統的開發者。許多新開發者常常不瞭解版本控制。另一些開發者覺得“這只是一個小專案”,所以沒必要用版本控制。大錯特錯。

  這裡列出所有工具,沒有一個比使用版本控制系統更加有好處。

  以前,我僅提到使用git作為一個(D)VCS。然而,對於使用Python的專案,Mercurial是一個合適的基於Python的替代者。這兩個工具都非常流行,網上有豐富的學習資源。確保你安裝了git或者Mercurial。這兩個工具基本都在你所用發行版的包管理系統中。

  如果你打算使用git,Github顯然是一個用來存放遠端倉庫的選擇。若是用Mercurial,Atlassian的Bitbucket是一個不錯的選擇(它也支援git,你可以使用任一方式)。

  (原始碼)控制你的環境

  即使還沒正式做什麼,我們知道我們將需要使用原始碼管理所有東西。我們有兩種將要提交的“內容”:我們的原始碼本身(包括模板等),像資料庫裝置、South遷移(以後會越來越多)和一個需求檔案等支援檔案。在以前的博文中,我建議提交你的真實虛擬環境,但也有些不錯的理由不這麼幹,至少這不是必須的。使用需求檔案可以給你帶來很多好處,而不需要額外的開銷。

  讓我們開始建立專案資料夾。使用django_admin.py中的新建專案命令來建立。

$ django_admin.py startproject django_project

  我們將看到建立的資料夾:django_project。在django_project資料夾內,我們將看到另一個django_project資料夾,裡面包含了一些常見的檔案:setting.py,urls.py和wsgi.py。在與第二個django_project同一目錄的是manage.py檔案。

  插曲:專案vs.應用程式

  你也許會好奇,為什麼已經有了新建應用程式的命令還要增加新建專案的命令。答案在於Django“專案”和Django“應用程式”的區別,這在Django1.4裡面有詳細的描述。簡單來說,一個專案是一套完整的網站或者應用。一個“應用程式”是一個可以用在任何Django專案中的很小的、(希望是)獨立的Django應用。如果你正在構建一個叫做“超級部落格”的部落格應用,那麼“超級部落格”就是你的Django專案。如果“超級部落格”支援讀者投票,那“投票”就是被“超級部落格“使用的一個Django應用程式。這個概念就是需要你的投票應用程式可以應用在其他需要使用者投票的Django專案中,而不是僅能應用在”超級部落格“專案中。一個專案就是一堆應用程式按照專案特定的邏輯構建的一個集合。一個應用程式可以應用在多個專案中。

  儘管你會本能地傾向於在你的“投票”程式中包含大量"超級部落格"的特定程式碼和資訊,但避免這樣有許多好處。基於鬆耦合的原理,講你的應用編寫為一個獨立的實體可以保持設計意圖,並且可以避免專案裡的bug直接影響到你的應用。這也意味著,如果你希望的話,你可以把你的任何應用程式發給另一個開發者,且他們不需要訪問或更改你的主專案。

  像軟體開發中的許多事情一樣,這需要一點付出,但回報很豐厚。

  建立我們的庫

  現在我們的專案裡已經有一些“程式碼”了(確實來說只是一些股票指令碼和空的配置檔案,恕我這樣說),現在是我們初始我們原始碼控制庫再好不過的時間了。下面是在Git和Mercurial中實現的步驟。

  git

$ git init

  這條命令在當前目錄建立了一個git倉庫。將我們所有的檔案新增到git以便提交。

$ git add django_project

  現在,我們將程式碼切實提交到我們的新庫中:

$ git commit -m 'Initial commit of django_project' 

  Mercurial

$ hg init

  這條命令在當前目錄建立了一個Mercurial倉庫。將我們所有的檔案新增到git以便提交。

$ hg add django_project

  現在,我們將程式碼切實提交到我們的新庫中:

$ hg commit -m 'Initial commit of django_project' 

  如果你打算使用像GitHub或者Bitbucket,現在是時候把程式碼push上去了。

  使用South進行資料庫遷移

  Django中最令人沮喪的特性之一是管理模型的變化和資料庫的相關變化。有了South的幫助,你可以實現建立一個完整的應用,而不需要寫具體的資料庫程式碼。South會建立一個遷移檔案來檢測你的模型變化,並自動在資料庫中生成。這使得你既可以前向根據最新變化來遷移資料庫,又可以後向取消一個變化或者一系列變化。它讓你的生活如此簡單,Django發行版沒有包含它真讓人吃驚(已經有人談論在Django中包含資料庫遷移工具,只是還沒發生)。

  依舊在我們的虛擬環境,像這樣安裝South:

$ pip install south

  我們在專案的settings.py檔案中把South新增到INSTALLED_APS中。現在就新增,包括你的專案中的資料庫設定,然後執行python manage.py syncdb。你將需要提升許可權使用超級使用者名稱和密碼(你可以輸入然後回車)。更重要的是,South已經在資料庫中設定好了它需要用的表格。

  你可能認識到我們並沒有在專案中新增應用,而只是執行了 syncdb。先這樣做可以讓 South 在一開始的時候就被安裝。使用 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 模式。例如,我的檔案內容多半就是:
*.pyc .*swp 

  在我們提交之前,還有一個資訊需要檢視:我們已經安裝的 Python 包。我們希望能夠追蹤使用到的 Python 包的名稱版本,這樣一來,我們就可以輕鬆的重建生產環境。pip 正好有個命令可以完成這個。

$ pip freeze > requirements.txt

  我將 pip 的輸出存入名為 requirements.txt 的檔案,並將這個檔案新增到程式碼控制中。這樣,在需要時,我們就有了一個包的列表。

  現在將 settings.py 及 requirements.txt 新增到提交檔案中,並提交:

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

  建立我們的應用

  以正常的方式使用manage.py來建立一個應用(python manage.py startapp myapp),並把它加入到INSTALLED_APP中。在新增模型前,我們要做的第一件事是我們告訴South我們想用它做遷移:

$ python manage.py schemamigration myapp --initial

  這將建立一個移植檔案,用來應用我們的更改(如果我們有的話),也可以用來 恢復更改。我們使用移植檔案來 移植資料庫的變化(即使還沒有變化),命令如下:

$ python manage.py migrate myapp

  South足夠智慧,知道去哪裡找到移植檔案,也記得我們做的最後的移植。你可以指定單獨的移植檔案,但這一般並不是必須的。

  當我們最終對模型做出改變時,我們使用下面的命令來讓South建立一個移植檔案:

$ python manage.py schemamigration myapp --auto

  這將檢測myapp中的模型,並自動相應的新增、刪除或修改資料庫中的表。然後使用如上的 移植命令就可以將改變應用到資料庫上。

  我們的開發區域

  還有一件事你需要注意:將開發區域與你已經確認的檔案區分開,原因顯而易見。使用Git和Mercurial實現這個很簡單,而且也有助於部署。建立django_project所在目錄之外的一個目錄作為你開發區域(我把它叫做dev)。

  在你的開發目錄,使用git或Mercurial克隆當前專案:

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

  兩個工具都將建立庫的一份完整拷貝。所有的更改、分支及歷史都將在新庫中可用。從現在起,你應該在你的開發目錄工作。

  由於使用Git和Mercurial來進行分支都容易便捷,當你切換新分支或站點的大規模變化時建立分支。下面是兩個工具的實現方法:

  (git)

$ git checkout -b <branchname>

  這不僅建立了一個命名新分支且會將程式碼檢出。幾乎所有的開發都應該在分支上,這樣主分支可以隨時恢復。

  (Mercurial)

$ hg branch <branchname>

  請注意,在Mercurial社群裡分支是一個有爭議的話題,目前這裡有一些可用的選項,但其中還沒有“顯然正確”的。在這裡,我使用命名分支,這可能是最安全且最有益的分支風格。任何在branch命令後的提交將在新分支生效。

  使用 Fabric 部署

  所以我們做好了一個Django專案。該怎樣部署呢?Fabric 。對於一個合理大小的專案,討論任何別的東西都是在浪費時間。Fabric可以用於多種目的,但在用於部署的時候,它確實非常閃亮。

$ pip install fabric

  Fabric需要一個名為fabfile.py的fabfile檔案,它定義了我們可以採取的所有動作。現在我們建立它。將下面這些放在專案根目錄下的fabfile.py檔案裡。

from fabric.api import local

def prepare_deployment(branch_name):
    local('python manage.py test django_project')
    local('git add -p && git commit') # or local('hg add && hg commit')

  它將執行這個測試並提交你的變更,但僅僅在你的測試通過的情況下。這時候,在你的生產區域一個簡單的"pull"就可以成為你的部署。為了實際部署我們再加一點東西。將這些加到fabfile.py:

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')

  它將從開發的主分支pull你的變更,執行任何你做出的遷移,執行你的測試,並重啟你的web伺服器。所有這些只需命令列中的一條簡單的命令。如果這些步驟之一失敗了,指令碼將停止並報告發生了什麼。一旦你修復了這個問題,也不需要再手工執行剩下的步驟。由於它們是冪等的,你可以簡單地重新執行部署命令,一切都會好起來的。

  注意上面的程式碼假定您正在開發部署在同一臺機器上。如果不是這樣,檔案將基本相同,但是要用Fabric的run函式代替local。請參見 Fabric文件 獲取更多細節。

  現在我們將fabfile.py建立好了,我們怎麼真正的部署呢?簡單,只需執行:

$ fab prepare_deployment $ fab deploy

  從技術上來說,這些可以組合成一條單獨的命令,但我發現明確的準備部署再去部署要更好,因為這使你更關注於你正在做的事情。

  享受你的新Django應用

  就這樣了!你已準備好開始實際開發。如果你做過很多Django開發,只需將上面所有的命令轉移到一個fabfile檔案,並將一個適當的Django應用建立為一個單步過程。我有一個會在今後上傳到我的GitHub帳號。如果你有任何問題或者修正,或者認為有一個工具/步驟我遺漏了,請隨時給我email jeff@jeffknupp.com 或者在下面留下評論。在Twitter上關注我 獲取所有部落格的最新更新!

  原文地址:starting-a-django-14-project-the-right-way

相關文章