【问题标题】:How to create a django package without setting DJANGO_SETTINGS_MODULE as environment variable?如何在不将 DJANGO_SETTINGS_MODULE 设置为环境变量的情况下创建 django 包?
【发布时间】:2020-03-15 18:00:09
【问题描述】:

我正在创建一个本身使用 Django 的包,我将在其他 Django 应用程序中使用它。我面临的主要问题是由于各种原因,例如日志记录和其他广泛的要求,我需要使用设置。因为,这个包没有任何视图/url,我们正在编写测试并使用 pytest 来运行它们。如果没有配置设置,测试将不会运行。因此,最初我将以下 sn-p 放入根应用程序的 __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__ 中工作(尝试过但有些不对,显示应用程序未加载)

我也试过这个,我将我的设置作为默认值导入,并使用它们作为默认值调用配置,并调用 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 设置的包,请分享。

【问题讨论】:

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


    【解决方案1】:

    所以我最终找到了一种无需将设置模块设置为环境变量的工作方式。这使我能够通过从以下位置导入所有被覆盖的设置以及默认设置来使用指定的设置:

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

    # my_package/apps.py
    
    from django.apps import AppConfig
    
    
    class MyPackageConfig(AppConfig):
        name = 'my_package'
        verbose_name = 'My package'
    

    而且,在你的包的根目录中。 __init__.py 中的以下 sn-p 只会设置被覆盖的设置:

    # 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(overridden_settings, 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. 如上述文档中所述,您必须确保设置只配置一次,并且类似地调用 setup 方法一次,否则会引发异常。

    如果这有帮助,或者您能想出更好的解决方案,请告诉我。

    【讨论】:

    • 什么是 conf[attribute] = getattr(default, attribute) 中的“默认”?
    • @AndréLuís 这是一个错字,已修正,应该是overridden_settings。它将遍历 Django 默认设置的属性,然后复制覆盖设置中存在的字段。
    猜你喜欢
    • 2017-01-01
    • 1970-01-01
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 2015-10-04
    相关资源
    最近更新 更多