在第一部分的教程里面,我们搭建好了工作环境,并创建了TaskBuster项目。

现在,我们将为测试、开发和生产配置不同的环境,编辑不同的Django配置文件。

另外,我们将移除这些文件中的SECRET_KEY以保证其真正的安全。

下一步,我们将创建一个仓库,使用版本控制系统来管理我们的代码,并把代码上传到Bitbucket

准备好迎接下一部分了吗?下面是概览:


虚拟环境与依赖文件

当开始一个项目时,一个非常重要的事情是对你的项目进行版本控制。举例来说,想象一下你正在一台安装了Django 1.8的电脑上进行开发,然后你准备在一台安装了Django 1.6的服务器上进行部署。你的代码在本地上将正常工作,但是当你部署时,一些不兼容的错误将出现。如果同一个项目有多个开发者进行开发,并且他们各自安装了不同版本的包,那么也会出现上述问题。

taskbuster_virtual_environments

使用虚拟环境安装各自的包,使Django看起来像Cobra(眼镜蛇)!

这个问题的标准解决方法是整合所有的包,并使用requirements.txt文件保存其版本信息。这个文件包含的信息类似于:

1
2
Django==1.8
selenium==2.42.1

那怎么查看我们已经安装过那些包了呢?(不用担心你的虚拟环境中包版本与这儿不同)。

你可以通过这条命令来查看你当前虚拟环境下已安装的包:

1
$ pip freeze

从上面的输出可以看出,你可以通过把输出内容保存到文件里来完成requirements.txt的自动生成:

1
$ pip freeze > requirements.txt

然而,也许你已经注意到,Selenium只是在测试环境下需要安装,所以咱没必要在开发和生产环境中安装这个包。

让我们这样解决这个问题:创建一个requirements的文件夹,并为每一个环境创建一个依赖文件。进入taskbuster_project文件夹,输入:

1
2
$ mkdir requirements
$ touch requirements/{base.txt,development.txt,production.txt,testing.txt}

注意:不要在touch这个命令中添加额外的空格,否则它不会正常工作 :-) 现在你可以把之前的requirements.txt删掉,因为我们已经不需要它了。另外,如果你计划在一台生产服务器中运行一个半私人的版本站点,你也可以创建一个staging.txt文件。

让我们首先编辑base.txt文件。这个文件将包含所有环境共有的包。现在,它应该只包含Django版本的内容:

1
2
$ cd requirements
$ echo "Django==1.8" >> base.txt

如果你使用的是其它的Django版本,那请替换成你自己的!

现在让我们把其它的三个文件继承base.txt的内容:

1
2
3
$ echo "-r base.txt" >> development.txt
$ echo "-r base.txt" >> testing.txt
$ echo "-r base.txt" >> production.txt

最后,我们需要把Selenium加入到testing.txt中:

1
$ echo "selenium==2.42.1" >> testing.txt

同样的,请写入你自己的版本。

Ok,现在已万事俱备。当团队有新成员加入时,我们将告诉他需要创建两个不同的环境,一个用于测试,一个用于开发(生产环境是用来部署的)。

接下来,他只需要激活这些环境,并安装相应环境下的requirements.txt中的包即可:

1
2
3
4
5
$ workon tb_dev
$ pip install -r requirements/development.txt

$ workon tb_test
$ pip install -r requirements/testing.txt

不同的环境使用不同的配置文件

之前设定的每一个环境都有一个不同的目的,因此,它们需要不同的配置。例如,开发和部署环境的数据库配置可能不同,测试环境中使用的包可能在其他环境中不需要(比如selenium)。

这就是我们要为不同环境设定不同配置文件的原因。首先,我们将在taskbuster文件夹中创建一个包含配置文件的子文件夹:

1
$ mkdir taskbuster/settings

这个文件夹将包含:

让我们创建这些文件先,所有的文件将置于taskbuster/settings文件夹:

1
2
$ cd taskbuster/settings
$ touch __init__.py development.py testing.py production.py staging.py

并编辑每一个文件,让它们继承base.py的内容:

1
2
# -*- coding: utf-8 -*-
from .base import *

最后,我们需要移动并重命名Django创建的settings.py文件为settings文件夹下的base.py。在settings文件夹下,你需要输入:

1
$ mv ../settings.py base.py

创建好这些文件后,我们需要为不同的虚拟环境制定正确的配置文件。

通过virtualenvwrapper,我们可以配置不同的钩子,这些钩子将在激活虚拟环境前后,退出虚拟环境前后被刷新。这意味着我们可以定义一些将在虚拟环境工作周期的不同阶段运行的命令。这些钩子保存在各虚拟环境主目录的bin文件夹下,即preactivatepostactivatepredeactivatepostdeactivate

在我们的例子里,我们让postactivate在虚拟环境激活后设定好DJANGO_SETTINGS_MODULE变量,并在退出虚拟环境后,使用predeactivate清除它。

1
2
$ workon tb_dev
$ cd $VIRTUAL_ENV/bin

后面一条命令将带你进入虚拟环境主目录的bin目录,那些不同的钩子就在里面。编辑postactivate文件,加上:

1
export DJANGO_SETTINGS_MODULE="taskbuster.settings.development"

编辑predeactivate文件,加上:

1
unset DJANGO_SETTINGS_MODULE

在测试环境中进行同样的工作,只是做如下更改:

1
export DJANGO_SETTINGS_MODULE="taskbuster.settings.testing"

是时候运行一下啦!回到taskbuster_project目录,激活你的开发环境。然后运行:

1
$ python manage.py runserver

在输出中你应该会看到一条表明你正在使用taskbuster.settings.development配置文件的消息:

1
Django version 1.8, using settings 'taskbuster.settings.development'

另开一个终端标签(保持之前的服务器处于激活状态),激活测试环境。核对一下测试环境是否使用的是taskbuster.settings.testing。也许你会被告知当前端口已经被开发环境占用了,因此我们需要为其指定另一端口:

1
$ python manage.py runserver 127.0.0.1:8001

接下来,掐断测试环境的服务器,并运行功能测试:

1
$ python functional_tests/all_users.py

Yes!我们并没有破坏什么东西 :-)

生产环境设置 – 禁止调试

在生产环境中,将DEBUG和TEMPLATE_DEBUG设为False是非常重要的。

首先,将这俩从base.py剪切至development.pytesting.py中,并设置其为True:

1
2
DEBUG = True
TEMPLATE_DEBUG = True

然后,把它们复制到production.py中,并设置其为False:

1
2
DEBUG = False
TEMPLATE_DEBUG = False

这样,这俩变量在各自的环境中已经有了正确的值。如果你还有staging.py,那么也请复制这两变量到此文件中。

Django安全与密钥(Secret Key)

如果你打开taskbuster/settings/base.py,你会看到一个名为SECRET_KEY的变量。这个变量应该保密,因此隔离出版本控制系统。

你可以直接把base.py加入到.gitignore文件中,这是直接把它从版本控制系统中移除的方法。然而,在项目开发过程中,这个文件将经历诸多变化,所以应该把它保留在版本控制系统中,尤其当你想与其他开发者共享它的时候。因此,一个更好的方法是移除密钥,而选择从其它地方导入这个密钥。这个其它地方则应该隔离出版本控制系统。

这里我们将把密钥保存在虚拟环境配置中,并从虚拟环境中获取密钥,并将其导入base.py中。

注意:如果你在使用Apache,这个方法将失效。最好的方法是把密钥保存在某个文件中,然后从中导入至base.py。而这个文件应该从版本控制系统中移除,并将其加入到.gitignore中。我推荐你阅读Two Scoops of Django 1.6这本书的章节5.4(目前此书已更新至Django 1.8)

要将密钥置于虚拟环境中,我们同样需要virtualenvwrapperpostactivatepredeactivate钩子。

激活你的tb_dev环境,进入bin

1
$ cd $VIRTUAL_ENV/bin

如果输入ls,你将看到我们刚提到的这些文件。编辑postactivate,加入密钥:

1
export SECRET_KEY="your_secret_django_key"

注意:不要在=号周围添加任何空格。

然后编辑predeactivate文件,加入这行代码:

1
unset SECRET_KEY

如此之后,如果你输入:

1
2
3
4
5
$ workon tb_dev
$ echo $SECRET_KEY
your_secret_django_key
$ deactivate
$ echo $SECRET_KEY

最后一行表明这里没有任何输出。这意味着SECRET_KEY只能在当前虚拟环境中可见,如你所愿。

tb_test虚拟环境中重复相同的步骤

最后,编辑base.py,移除SECRET_KEY,加入下面的代码:

1
2
3
4
5
6
7
8
9
10
11
from django.core.exceptions import ImproperlyConfigured


def get_env_variable(var_name):
try:
return os.environ[var_name]
except KeyError:
error_msg = "Set the %s environment variable" % var_name
raise ImproperlyConfigured(error_msg)

SECRET_KEY = get_env_variable('SECRET_KEY')

函数get_env_variable会尝试从环境中获取var_name变量,如果没找着,则报ImproperlyConfigured错误。这样,当你尝试运行你的应用,并且SECRET_KEY不存在,我们将看到一条表明我们项目失败原因的消息。

让我们核对一下是否所有的工作都跟我们期待的一致。保存base.py,退出这俩虚拟环境,然后在不同的终端标签中再次激活它们

tb_dev中运行开发服务器

1
$ python manage.py runserver

然后在tb_test中运行功能测试

1
$ python functional_tests/all_users.py

希望你的测试也能成功!! :-)

注意:当你部署你的app的时候,你需要在你的服务器中指定SECRET_KEY。例如,如果你使用Heroku,你可以使用:

1
$ heroku config:set SECRET_KEY="your_secret_key"

请别担心,我们将在后续的教程中讲述Heroku :-)

初始化Git仓库并进行提交

Ok!现在我们可以开始将项目提交至新的仓库中去啦!友情提示:这里有份基础的git教程

进入taskbuster_project目录,输入:

1
$ git init .

它将在当前目录里初始化仓库。你将看到一个名为.git的新文件夹,它里面包含了刚创建的仓库。

在添加文件进仓库之前,我们需要想想这里是否有我们不需要放进版本控制系统中的文件。

注意,在运行开发服务器之后,我们将得到下面的额外文件:

这俩应该从版本控制系统中移除。创建一个.gitignore文件,并写入:

1
db.sqlite3
__pycache__
TaskBuster.sublime-workspace

这里我们也写入了sublime text的工作目录(如同我们在第一部分教程中看到的那样,当创建一个项目时,sublime text会生成两个不同的文件。我们只需要对以-project结尾的文件做版本控制,而以-workspace结尾的文件则不需要)。

接下来,让我们把当前目录下所有文件添加至暂存区(除了.gitignore设置的文件):

1
$ git add .

然后使用下面的命令查看添加至暂存区的文件:

1
$ git status

你应该可以看到如下图所示的内容,所有新加入的文件标绿:

Terminal First commit

如果你看到有你不想提交的文件,你可以这样移除它们:

1
$ git rm --cached path_of_file

不要忘了把它们加入到.gitignore,这样方便后续提交。

最后,让我们提交我们的更改:

1
$ git commit -m "Taskbuster project created"

-m标识表明后面的文字是用来描述这次提交的。如果你只输入git commit,一个编辑器将自动打开,让你写入提交的描述文字(默认的编辑器是vi

你可以使用下面的命令查看已执行的提交:

1
$ git log

将项目上传至Bitbucket

如果你没有Bitbucket账号,请创建一个先,然后再新建一个仓库。之所以使用Bitbucket是因为它允许创建私人仓库,当然我们这里涉及到的操作步骤与Github差不多。

你需要确定这个仓库的链接,如同:

https://user_name@bitbucket.org/user_name/repository_name.git

你可以按Overview -> Command line --> I have an existing project这样的导航找到它。

首先我们需要添加Bitbucket作为一个远程仓库。进入taskbuster_project目录,输入:

1
$ git remote add origin https://user_name@bitbucket.org/user_name/repository_name.git

这里你需要写成你自己的仓库链接地址。注意:前面的命令只有一行。它将把你的Bitbucket仓库别名为origin(使用origin作为远程仓库的别名是一个惯用法)。

接下来,让我们把仓库推送至这个新的Bitbucket仓库:

1
$ git push -u origin --all

-all标识可以使refs/heads下所有的refs被推送,-u标识代表--set-upstream添加一个跟踪引用)。之后你可能需要输入你的密码。

最后,你将看到这样的消息:

1
Branch master set up to track remote branch master from origin.

你可以使用下面的命令查看当前活动的分支:

1
2
3
$ git branch -a
* master
remotes/origin/master

Okay!现在我们第一个项目已经有了一个好的工作环境了,并且我们已经将它进行了版本控制,现在我们可以开始我们的主页啦!

但是…我还没有讨论创建models,仅仅讲述配置static和templates文件,这样将得到一个包含一些CSS文件的漂亮主页 – 我讨厌没有CSS的开发,所以这常常是我做的第一件事。

请在下一部分教程中去探索更这相关的更多内容!使用TDD,Staticfiles和Templates配置来创建一个主页

请把本教程分享给你的开发者朋友!:-)