最近发现 Django settings 在使用的时候,容易出现不经过检查的问题。
因此,想要在 settings 的基础上严格约束一下,减少问题。
在进行相关技术调研的时候,发现了django-class-settings这个库。
实现方式很有意思,于是就调研了一下,学习到了很多新的东西。
这个库的核心思想,是在代码中,把一个类转换成一个 module;
这非常酷,让我们看看这是如何实现的。
按照代码的阅读思路,我们首先看看这个包的用法…
以下是README.md中的内容;
django-class-settings aims to simplify complicated settings layouts by using
classes instead of modules. Some of the benefits of using classes include:
- Real inheritance
 - [Foolproof settings layouts][local_settings]
 - Properties
 - Implicit environment variable names
 
Example
1
2
3
  | # .env
export DJANGO_SECRET_KEY='*2#fz@c0w5fe8f-'
export DJANGO_DEBUG=true
  | 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
  | # manage.py
import os
import sys
import class_settings
from class_settings import env
from django.core.management import execute_from_command_line
if __name__ == '__main__':
    env.read_env()
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
    os.environ.setdefault('DJANGO_SETTINGS_CLASS', 'MySettings')
    class_settings.setup()
    execute_from_command_line(sys.argv)
  | 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
  | # myproject/settings.py
from class_settings import Settings, env
class MySettings(Settings):
    SECRET_KEY = env()
    DEBUG = env.bool(default=False)
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    ]
    ROOT_URLCONF = 'myproject.urls'
    WSGI_APPLICATION = 'myproject.wsgi.application'
  | 
Installation
Install it from [PyPI][pypi-url] with [pip][pip-url]:
1
  | pip install django-class-settings
  | 
我们可以看到,这个类关键入口可能在env.read_env()以及class_settings.setup()。
我们首先看一下 src.class_settings.env 的代码。可以发现,这个代码用于加载 django 中的 env;
因此不是我们关注的重点。
让我们再看看关键函数 setup。
src/class_settings/__init__.py:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  | __all__ = ["Env", "Settings", "env", "setup"]
__version__ = "0.3.0-dev"
from .env import Env, env
from .settings import Settings
def setup():
    import sys
    from django.conf import settings
    from django.utils.functional import SimpleLazyObject
    from .importers import SettingsImporter, LazySettingsModule
    global _setup
    if _setup:
        return
    sys.meta_path.append(SettingsImporter)
    default_settings = LazySettingsModule()
    settings_module = SimpleLazyObject(lambda: default_settings.SETTINGS_MODULE)
    settings.configure(default_settings, SETTINGS_MODULE=settings_module)
    _setup = True
_setup = False
  | 
在.settings.py中没有直接加载的代码,因此,我们可以直接阅读本文件。
未完待续…