如何在不将DJANGO_SETTINGS_MODULE设置为环境变量的情况下创建django包?

时间:2019-11-20 05:20:55

标签: django environment-variables django-settings python-packaging

我正在创建一个本身使用Django的软件包,并将在其他Django应用程序中使用它。我面临的主要问题是由于各种原因(例如日志记录和其他广泛的要求),我需要使用设置。由于此程序包没有任何视图/ URL,因此我们正在编写测试,并使用pytest运行它们。如果未配置设置,则无法运行测试。因此,最初,我将以下代码片段放在根应用程序的__init__文件中。

import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_package.settings")
django.setup()

现在,测试正常运行,并且作为独立应用程序的程序包正在运行。但是,一旦我将其安装在主项目中,它就会使用其自身的设置覆盖该环境变量,并且您可以想象它会造成什么样的破坏。

这是我第一次打包Django应用。因此,我对最佳实践并不了解,并且文档有些混乱。我阅读了使用其程序包中的设置的各种程序包的结构和代码,但我仍然无法理解如何确保程序包访问预期的设置,并且不会同时影响项目的设置。

遍历文档时,我遇到了设置DJANGO_SETTINGS_MODULE的替代方法,如下所示:

from django.conf import settings
settings.configure(DEBUG=True)

如此处所示:https://docs.djangoproject.com/en/2.2/topics/settings/#using-settings-without-setting-django-settings-module

但是我应该在哪里添加呢?对于导入设置或将在__init__中工作的每个文件(尝试过此操作但不正确,表明未加载应用)

我也尝试了此操作,在此我将设置导入为默认设置,并使用它们作为默认设置调用了configure,并调用了django.setup(),但没有成功:

# my_package/__init__.py

from django.conf import settings
from my_package import settings as default
if not settings.configured:
    settings.configure(default_settings=default, DEBUG=True)

import django
django.setup()

此外,我需要设置主要是因为我有几个参数可以在使用该程序包的项目中覆盖。安装软件包后,覆盖的变量将是我在运行时可以在软件包中访问的变量。

如果有人可以指导如何解决此问题,或者有更好的过程来创建需要Django设置的软件包,请共享。

1 个答案:

答案 0 :(得分:0)

因此,我最终找到了一种无需将设置模块设置为环境变量的工作方法。这样,我就可以通过导入所有覆盖的设置以及来自以下位置的默认设置来使用指定的设置:

创建一个用于将程序包配置为应用程序的应用程序文件。

# my_package/apps.py

from django.apps import AppConfig


class MyPackageConfig(AppConfig):
    name = 'my_package'
    verbose_name = 'My package'

然后,在包的根目录中。 __init__.py中的以下代码段将仅设置覆盖的设置:

# my_package/__init__.py

from django.conf import settings


import django

from my_package import settings as overridden_settings
from django.conf import settings

default_app_config = 'my_package.apps.MyPackageConfig'

if not settings.configured:
    # Get the list of attributes the module has
    attributes = dir(overridden_settings)
    conf = {}

    for attribute in attributes:
        # If the attribute is upper-cased i.e. a settings variable, then copy it into conf
        if attribute.isupper():
            conf[attribute] = getattr(default, attribute)

    # Configure settings using the settings
    settings.configure(**conf)

    # This is needed since it is a standalone django package
    django.setup()

django.setup()的用途参考: https://docs.djangoproject.com/en/2.2/topics/settings/#calling-django-setup-is-required-for-standalone-django-usage

要记住的要点: 1.由于它位于__init__中,因此可以确保如果您从软件包中导入内容,则配置已配置。 2.如以上文档所述,您必须确保仅对设置进行一次配置,并且类似地,一次调用设置方法,否则将引发异常。

让我知道这是否有帮助,或者您能够提出一个更好的解决方案。