参考文献:http://www.loonapp.com/blog/11/ https://blog.csdn.net/weixin_42829741/article/details/107950048
工程根目录优化
- 假设我新创建了一个名为 my_project 的 Django 工程,初始的目录结构是这样的
my_project ├── manage.py └── my_project ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py
其中我们知道
- urls.py 中描述了项目最高级路由
- settings.py 提供了项目整体的设置
- asgi.py 和 wsgi.py 负责提供了项目网关入口
- 第二层的 my_project 文件夹中存放着与项目配置相关的文件
- manage.py 是项目的管理脚本文件
# python manage.py startapp foo # python manage.py startapp bar my_project ├── bar │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ ├── models.py │ ├── tests.py │ └── views.py ├── foo │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ ├── models.py │ ├── tests.py │ └── views.py ├── manage.py └── my_project ├── __init__.py ├── __pycache__ ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py
-
如你所见,我们为项目添加了两个 app ,一个 foo 和一个 bar 。这时候问题就出现了,按照 Django 项目默认的组织逻辑, app 直接创建在根目录下,而项目的配置信息则存在于根目录下的同名文件夹内,这就造成了下列问题
-
项目下与项目同名的文件夹让人迷惑
-
app 目录和项目配置文件夹没有明确差异
-
- 下面我们来分别解决这一问题
分离项目配置
- 在实际业务中,项目配置往往都存放于项目根目录路径下,因此在这里我们不妨也这么做,简单来说就是将第二层的 my_project 文件夹中的东西全部拿出来,然后删除 my_project 文件夹,现在你的项目看起来应该是这样的。
my_project ├── __init__.py ├── bar │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ ├── models.py │ ├── tests.py │ └── views.py ├── foo │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ ├── models.py │ ├── tests.py │ └── views.py ├── asgi.py ├── manage.py ├── settings.py ├── urls.py └── wsgi.py
-
仅仅把内容拿出来是不够的,我们还需要改变拿出来的文件的信息。先让我们看看 asgi.py
# 原来的信息表示他的配置文件参考my_project.settings,我们把settings提升到根目录,因此可以去掉my_project # os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_project.settings') # 修改后 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
-
然后是 wsgi.py ,和 asgi.py 更改的逻辑相同,都是去掉 my_project.
- 然后是manage.py ;作为项目的入口文件,我们看到他同样需要更换 settings 的路径
# 修改前 # os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_project.settings') # 修改后 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
-
下面修改 settings.py
# 修改根url # 修改前:ROOT_URLCONF = 'my_project.urls' ROOT_URLCONF = 'urls' # 修改wsgi # 修改前:WSGI_APPLICATION = 'my_project.wsgi.application' WSGI_APPLICATION = 'wsgi.application'
整理项目apps
- 在实际的项目中,我们更希望把 apps 放在一个文件夹进行整理,下面我们就来做这一步工作。项目下新建名为 apps 的 py 包,把 bar/ 和 foo/ 都扔进去
my_project ├── __init__.py │ ├── apps │ ├── __init__.py │ ├── bar/ │ └── foo/ ├── asgi.py ├── manage.py ├── settings.py ├── urls.py └── wsgi.py
这种情况下,在 settings.py 内进行相应调整
# 将apps/加入系统路径 sys.path.insert(0, os.path.join(BASE_DIR, 'apps')) # 注册app时 INSTALLED_APPS = [ 'apps.foo', # 添加 apps. 'apps.bar', # …… ]
拆分settings
- 配置信息也需要模块化!将 settings.py 从一个文件转化为一个 python 模块,再将原有的 settings.py 改名为 base.py 放在这个模块内,同时新建 prod.py 和 dev.py 分别指代开发环境和生产环境。项目结构现在看起来像这样
my_project ├── __init__.py │ ├── apps │ ├── __init__.py │ ├── bar │ └── foo ├── asgi.py ├── manage.py ├── settings │ ├── __init__.py │ ├── base.py │ ├── dev.py │ └── prod.py ├── urls.py └── wsgi.py
-
下面我们来举几个例子说明哪些配置应当被拆分出来
# base.py # 项目密钥 SECRET_KEY = '' # 是否为DEBUG状态 DEBUG = True #允许访问主机 ALLOWED_HOSTS = [] # 数据库配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }
# dev.py from .base import * # 开发环境密钥 SECRET_KEY = 'xxxxxxxxxxxxxxxxx' # 开发环境,DEBUG=True DEBUG = True ALLOWED_HOSTS = ["*"] # 开发用数据库 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }
# prod.py from .base import * # 生产环境密钥 SECRET_KEY = 'yyyyyyyyyyyyyyyyyy' # 生产环境下,DEBUG=False DEBUG = False # 生产用数据库 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 数据库引擎 'NAME': 'django_mysql', # 数据库名 'USER': 'root', # 账号 'PASSWORD': 'root', # 密码 'HOST': '127.0.0.1', # HOST 'POST': 3306, # 端口 } }
观察这几个配置的例子,可以发现,拆分配置的本质就是对base.py内变量的重写。
-
配置拆分完成之后,我们还需指定启动项目所需的配置文件。这部分有点类似我们在分离项目配置时做的那样,只不过这次从删除变成了增加
# manage.py # 开发环境下常用manage.py启动项目,因此默认设置采用dev os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.dev') # asgi.py/wsgi.py # 生产环境下常用asgi/wsgi,默认采用prod os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.prod')
-
此外,也可以在命令行内设置本次命令执行时采用的配置
# 临时使用prod配置启动项目 python manage.py runserver --setting=setting.prod
requirements.txt
- 在工程目录中创建一个顶级的 requirement.txt 是必须遵循的要求,而且这样可以保证可以方便地管理工程依赖关系;但这也意味着:很有可能,工程的开发环境依赖关系不同于你的生产环境,所有你需要将你的开发和生产环境的依赖都放到 requirement.txt中,但是这会使得管理起来比较困难。所以,最好是区分好不同环境的依赖和需求
my_project ├── __init__.py ├── apps ├── asgi.py ├── manage.py ├── settings ├── urls.py ├── wsgi.py └── requirements ├── base.txt ├── dev.txt └── prod.txt
可以看出,我新建了一个顶级目录:requirements ,包含一系列的需求说明文件,分别针对每个环境。
-
base.txt 内含各种环境下共享的需求说明。例如 Django 。所有环境下都需要 Django ,不管是开发环境还是生产环境,你都需要使用它。
-
将各类需求文件分开的目的是,当作为程序员的我只需要在本地环境下运行项目,那么我只需要安装 dev.txt 中提及的依赖包,而不需要安装其他的包。
-
但是为什么我这么关心哪些包是我必须安装的?为什么我不将他们全部安装?
安装依赖包需要耗费很长时间,对于大型项目来说可能会耗费大块的时间(30分钟以上)。
很多需求依赖于外部软件或者库文件按装到你的本地机器来完成编译。这么避免安装库文件可以节省时间还可以免去大量不必要的麻烦,比如要安装哪个版本的 libxml2 和 libpq-dev 。
降低了初学者学习的门槛。如果的你项目组来了一个新的开发,尝试提交代码,对他来说安装很少的软件包就可以运行系统要比安装所有软件包要简单的多。
-
-
现在我们明白了为什么要模块化需求说明文件,下面了解下实践中需求说明文件的具体内容。
首先, base.txt 文件列出了所有基本的需求包,其中的么个软件包在任何环境都是必须的(不管是开发环境,测试环境还是生产环境等的):
# requirements/base.txt Django==1.4 django-cache-machine==0.6 django-celery==2.5.5 django-dajaxice==0.2 django-guardian==1.0.4 django-kombu==0.9.4 django-pagination==1.0.7 django-sorting==0.1 django-tastypie==0.9.11 Fabric==1.4.1 lxml==2.3.4 pyst2==0.4 South==0.7.4 Sphinx==1.1.3
dev.txt 文件包含了我的开发环境所需要包,其中的包只有是在开发环境下才会用到。
# requirements/dev.txt -r base.txt django-debug-toolbar==0.9.4
在我的开发环境,我通常使用轻量级的 SQLite3 数据库(所以我不需要安装任何驱动程序),而且非常好用的包 django-debug-toolbar 可以允许我检查数据库查询和性能问题,等等。可能你会疑惑文件第一行的作用, '-r base.txt' 告诉pip引入所有通用的依赖包附加到后面列举内容。这将允许我在命令行中直接运行 pip intal -r requirements/dev.txt 来安装base.txt声明的所有依赖包。
-