以正确的方式开始一个 Django 1.4 项目

  • A+
所属分类:Python

  早在二月份时,我写了一篇题为‘开始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 [email protected] 或者在下面留下评论。在Twitter上关注我 获取所有博客的最新更新!

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

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin