Django小技巧20: 使用多个settings模块

Django小技巧20: 使用多个settings模块

Posted November 09, 2018

翻译整理自: simpleisbetterthancomplex.com

通常来说, 为了保持项目的配置简单,我们会避免使用多个配置文件。但理想很丰满, 现实是随着项目越来越大, settings.py可能也会变得相当复杂. 在那种情况下, 你必须使用大量的if语句,类似于: if not DEBUG: # do something... .为了将development配置和production严格的分离,你可以将settings模块分解成多个文件. 这样对我们的配置可能更加清楚.

默认的基本结构

一个全新的 Django 项目结构默认情况下如下所示

Text only

mysite/
 |-- mysite/
 |    |-- __init__.py
 |    |-- settings.py
 |    |-- urls.py
 |    +-- wsgi.py
 +-- manage.py

我们在mysite目录中创建一个叫做settings的目录, 然后将原有的settings.py移动到 settings 目录中, 并更改名字为base.py. 如果使用 Python 2.x 增加__init__.py`文件.

Text only

mysite/
 |-- mysite/
 |    |-- __init__.py
 |    |-- settings/         <--
 |    |    |-- __init__.py  <--
 |    |    +-- base.py      <--
 |    |-- urls.py
 |    +-- wsgi.py
 +-- manage.py

顾名思义, base.py 将提供适用于所有环境(development, production, staging, 等)配置.

然后为每个环境创建一个settings模块. 常见的用例有

  • ci.py
  • development.py
  • production.py
  • staging.py

然后文件结构应该和下面类似:

Text only

mysite/
 |-- mysite/
 |    |-- __init__.py
 |    |-- settings/
 |    |    |-- __init__.py
 |    |    |-- base.py
 |    |    |-- ci.py
 |    |    |-- development.py
 |    |    |-- production.py
 |    |    +-- staging.py
 |    |-- urls.py
 |    +-- wsgi.py
 +-- manage.py

配置新的settings.py

依下面的base.py为例:

settings/base.py

Python

from decouple import config

SECRET_KEY = config('SECRET_KEY')

INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'mysite.core',
    'mysite.blog',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'mysite.urls'

WSGI_APPLICATION = 'mysite.wsgi.application'

为了保证实例简单, 我删除其他无效的代码

然后创建development.py配置文件, 我可以直接通过 base 来扩展.

settings/development.py

Python

from .base import *

DEBUG = True

INSTALLED_APPS += [
    'debug_toolbar',
]

MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

DEBUG_TOOLBAR_CONFIG = {
    'JQUERY_URL': '',
}

然后, 你可以这样定义production.py模块

Python

from .base import *

DEBUG = False

ALLOWED_HOSTS = ['mysite.com', ]

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.mailgun.org'
EMAIL_PORT = 587
EMAIL_HOST_USER = config('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')
EMAIL_USE_TLS = True

注意: 应该避免使用import *导入,*导入可能会在命名空间作用域中导入一些不必要的东西. 在某些情况下可能会产生冲突, 造成奇怪的问题. 另外一个问题是即使使用多个配置文件, 你依然要注意敏感数据的问题. 强烈推荐使用**Python-Decouple ** 这样的库来保护配置, 或者通过环境变量的形式使用密码或密钥配置.

如何使用多个配置文件

因为我们代码库中已经没有settings.py文件, 所以不能直接使用python manage.py runserver.相反你必须在命令参数中指定settings模块.

Bash

python manage.py runserver --settings=mysite.settings.development

Or

Bash

python manage.py migrate --settings=mysite.settings.production

由于我们在开发中经常使用 manage.py, 因此你可以在manage.py中, 硬编码写死配置模块.

manage.py

Python

#!/usr/bin/env python
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings.development")  # <-- Change here!
    try:
        from django.core.management import execute_from_command_line
    except ImportError:
        # The above import may fail for some other reason. Ensure that the
        # issue is really that Django is missing to avoid masking other
        # exceptions on Python 2.
        try:
            import django
        except ImportError:
            raise ImportError(
                "Couldn't import Django. Are you sure it's installed and "
                "available on your PYTHONPATH environment variable? Did you "
                "forget to activate a virtual environment?"
            )
        raise
    execute_from_command_line(sys.argv)

所以, 我们只改动了一行

Python

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

改为

Python

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings.development")

也许可以更稳妥

现在我们有了多个配置模块, 这样你可以将AUTHPASSWORDVALIDATORS配置从base.py中移动到production.py中. 这样, 你可以在开发环境中使用简单密码(如: 123). 但在生产环境中必须要通过密码验证才能使用.

在你测试环境中的配置文件中(settings/ci.py or settings/tests.py), 覆盖以下配置, 以便加快你的测试用例速度:

Python

DATABASES['default'] = {
    'ENGINE': 'django.db.backends.sqlite3'
}

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.MD5PasswordHasher',
)

结论

多个配置文件虽然提供了便利, 但你还是需要小心使用. 任何情况下都要考虑安全. 如果有疑问, 通过下面评论讨论.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏比原链

Derek解读Bytom源码-P2P网络 地址簿

Gitee地址:https://gitee.com/BytomBlockchain/bytom

1113
来自专栏比原链

Derek解读Bytom源码-P2P网络 地址簿

Gitee地址:https://gitee.com/BytomBlockchain/bytom

831
来自专栏张善友的专栏

HTTP Basic Authentication验证WCF Data Service

WCF Data Service是OData协议,也是RESTFul Service的一种,上篇文章已经介绍了HTTP Basic Authentication...

2108
来自专栏乐沙弥的世界

Linux script 命令记录(数据库)操作步骤

    对DBA而言,经常碰到升级数据库或是apply patch,以及有些时候需要运行大量的脚本。对于这些操作我们希望现在在屏幕同时又输出的文件以备后续查询过...

1264
来自专栏康怀帅的专栏

Nginx 编译安装

本文介绍了手动编译安装 nginx 的具体步骤。 安装依赖包 RedHat 系 $ yum install -y gcc gcc-c++ pcre-devel ...

3664
来自专栏安恒网络空间安全讲武堂

XCTF-赛博地球杯工业互联网安全大赛web部分题解

0x01工控云管理系统项目管理页面解析漏洞 题目首先给出了源码: `http://47.104.156.32:20007/view-source.php` 关键...

6088
来自专栏挖坑填坑

使用.net core ABP和Angular模板构建博客管理系统(实现博客列表页面)

1831
来自专栏FreeBuf

远程RPC溢出EXP编写实战之MS06-040

0x01 前言 MS06-040算是个比较老的洞了,在当年影响十分之广,基本上Microsoft大部分操作系统都受到了影响,威力不亚于17年爆出的”永恒之蓝”漏...

28310
来自专栏刘望舒

Android PMS的创建过程

PMS的创建过程分为两个部分进行讲解,分别是SyetemServer处理部分和PMS构造方法。其中SyetemServer处理部分和AMS和WMS的创建过程是类...

1023
来自专栏Kubernetes

原 荐 Kubernetes Resourc

更多关于kubernetes的深入文章,请看我csdn或者oschina的博客主页。 ResoureQuota介绍 关于ResoureQuota和Resourc...

5139

扫码关注云+社区

领取腾讯云代金券