gpt4 book ai didi

python - Django 应用程序默认设置?

转载 作者:行者123 更新时间:2023-12-03 01:04:41 25 4
gpt4 key购买 nike

我正在寻找一种方法来拥有易于使用、不易出错且开销很小的应用程序默认值和设置。

目前我组织如下:

myapp/defaults.py
# application defaults
import sys
if sys.platform == 'win32':
MYAPP_HOME_ROOT = os.path.dirname(os.environ['USERPROFILE'])
else:
MYAPP_HOME_ROOT = '/home'

在我的项目中,我有:
mysite/settings.py
from myapp.defaults import * # import all default from myapp
MYAPP_HOME_ROOT = '/export/home' # overriding myapp.defaults

通过此设置,我可以以常规 django 方式( from django.conf import settingssettings.XXX )导入和使用设置。

update-3(为什么我们需要这个)
  • 默认设置(“默认”):
  • 如果可以通过覆盖一组合理的默认设置来配置应用程序,则该应用程序使用起来会更方便。
  • 应用程序“具有领域知识”,因此它尽可能提供合理的默认值是有意义的。
  • 应用程序的用户需要提供每个应用程序所需的所有设置并不方便,覆盖一个小的子集并将其余的保留为默认值应该就足够了。
  • 如果默认值可以对环境使用react,这将非常有用。当 DEBUG 时,您通常会想做一些不同的事情。为真,但任何其他全局设置都可能有用:例如MYAPP_IDENTICON_DIR = os.path.join(settings.MEDIA_ROOT, 'identicons') ( https://en.wikipedia.org/wiki/Identicon )
  • 项目(站点/全局)设置必须覆盖应用默认值,即定义了 MYAPP_IDENTICON_DIR = 's3://myappbucket.example.com/identicons' 的用户在(全局)settings.py他们网站的文件应该得到这个值,而不是应用程序的默认值。
  • 任何接近使用设置的正常方式 ( import .. settings; settings.FOO ) 的解决方案都优于需要新语法的解决方案(因为新语法会有所不同,我们将获得新的和独特的方法来使用不同应用程序的设置)。
  • python的禅意可能适用于这里:
  • 如果实现很难解释,那是个坏主意。
  • 如果实现很容易解释,这可能是一个好主意。

  • (原帖提出了以下两个关键问题,没有说明上述假设。)

    问题 #1:当为应用程序运行单元测试时,没有站点,所以 settings不会有任何 myapp.defaults .

    问题#2:如果 myapp.defaults也有一个大问题需要使用设置中的任何内容(例如 settings.DEBUG ),因为您无法从 defaults.py 导入设置(因为那将是一个循环导入)。

    为了解决问题#1,我创建了一个间接层:
    myapp/conf.py
    from . import defaults
    from django.conf import settings

    class Conf(object):
    def __getattr__(self, attr):
    try:
    return getattr(settings, attr)
    except AttributeError:
    return getattr(defaults, attr)
    conf = Conf() # !<-- create Conf instance

    和用法:
    myapp/views.py
    from .conf import conf as settings
    ...
    print settings.MYAPP_HOME_ROOT # will print '/export/home' when used from mysite

    这允许 conf.py文件也可以使用“空”设置文件,并且 myapp 代码可以继续使用熟悉的 settings.XXX .

    它不能解决问题#2,基于例如定义应用程序设置 settings.DEBUG .我目前的解决方案是添加到 Conf类(class):
        from . import defaults
    from django.conf import settings

    class Conf(object):
    def __getattr__(self, attr):
    try:
    return getattr(settings, attr)
    except AttributeError:
    return getattr(defaults, attr)

    if settings.DEBUG:
    MYAPP_HOME_ROOT = '/Users'
    else:
    MYAPP_HOME_ROOT = '/data/media'
    conf = Conf() # !<-- create Conf instance

    但这并不令人满意,因为 mysite 无法再覆盖该设置,并且 myapp 的默认值/设置现在分布在两个文件中...

    有没有更简单的方法来做到这一点?

    更新 4:“只需使用 django 测试运行程序..”

    The app you are testing relies on the Django framework - and you cannot get around the fact that you need to bootstrap the framework first before you can test the app. Part of the bootstrapping process is creating a default settings.py and further using the django-supplied test runners to ensure that your apps are being testing in the environment that they are likely to be run.



    虽然这听起来应该是真的,但实际上并没有多大意义,例如没有默认值 settings.py (至少不是可重用的应用程序)。在谈论集成测试时,使用 site/settings/apps/database(s)/cache(s)/resource-limits/etc 测试应用程序是有意义的。它将在生产中遇到。然而,对于单元测试,我们只想测试我们正在查看的代码单元 - 尽可能少的外部依赖项(和设置)。 Django 测试运行器确实并且应该模拟框架的主要部分,因此不能说它在任何“真实”环境中运行。

    虽然 Django 测试运行器很棒,但它无法处理的问题列表很长。我们的两大难题是 (i) 顺序运行测试太慢以至于测试套件变得未使用(并行运行时 <5 分钟,顺序运行时将近一个小时),(ii) 有时您只需要在大型数据库上运行测试(我们将昨晚的备份恢复到测试可以运行的测试数据库 - 对于固定装置来说太大了)。

    制作nose、py.test、twill、Selenium 和任何模糊测试工具的人确实非常了解测试,因为这是他们唯一的关注点。不能借鉴他们的集体经验将是一种耻辱。

    我不是第一个遇到这个问题的人,而且似乎没有简单或通用的解决方案。这是两个具有不同解决方案的项目:

    更新,python-oidc-provider 方法 :

    python-oidc-provider 包 ( https://github.com/juanifioren/django-oidc-provider ) 有另一种创造性的方法来解决 app-settings/defaults 问题。它使用属性来定义 myapp/settings.py 中的默认值。文件:
    from django.conf import settings
    class DefaultSettings(object):
    @property
    def MYAPP_HOME_ROOT(self):
    return ...

    default_settings = DefaultSettings()

    def get(name):
    value = None
    try:
    value = getattr(default_settings, name)
    value = getattr(settings, name)
    except AttributeError:
    if value is None:
    raise Exception("Missing setting: " + name)

    使用 myapp 内的设置变为:
    from myapp import settings
    print settings.get('MYAPP_HOME_ROOT')

    好:解决问题#2(在定义默认值时使用设置),解决问题#1(使用来自测试的默认设置)。

    错误:访问设置的语法不同( settings.get('FOO') 与正常的 settings.FOO ),myapp 无法为将在 myapp 之外使用的设置提供默认值(您从 from django.conf import settings 获得的设置将不包含来自 myapp 的任何默认值)。外码可以做 from myapp import settings获取常规设置和 myapp 默认值,但如果有多个应用程序想要执行此操作,则此操作会崩溃...

    Update2,django-appconf 包:
    (注意:与 Django 的 AppConfig 无关..)

    django-appconfig , 应用设置在 myapp/conf.py 中创建(需要提前加载,因此您可能应该从 models.py 导入 conf.py 文件 - 因为它是提前加载的):
    from django.conf import settings
    from appconf import AppConf
    class MyAppConf(AppConf):
    HOME_ROOT = '...'

    用法:
    from myapp.conf import settings
    print settings.MYAPP_HOME_ROOT

    AppConf 会自动添加 MYAPP_前缀,并自动检测是否 MYAPP_HOME_ROOT已在项目设置中重新定义/覆盖。

    pro:使用简单,解决了问题#1(从测试访问应用程序设置)和问题#2(在定义默认值时使用设置)。只要提前加载了 conf.py 文件,外部代码就应该能够使用 myapp 中定义的默认值。

    骗局:非常神奇。 conf.py 中设置的名称与其用法不同(因为 appconf 会自动添加 MYAPP_ 前缀)。外部/不透明依赖。

    最佳答案

    我刚刚创建了 django-app-defaults基于所有要求。它基本上是问题( class Conf(object): )中强调的第二种方法的概括。

    用法:

    # my_app/defaults.py

    # `django.conf.settings` or any other module can be imported if needed

    # required
    DEFAULT_SETTINGS_MODULE = True

    # define default settings below
    MY_DEFAULT_SETTING = "yey"

    然后在您的项目中的任何地方:
    from app_defaults import settings

    print(settings.MY_DEFAULT_SETTING)
    # yey

    # All `django.conf.settings` are also available
    print(settings.DEBUG)
    # True

    要为单个应用程序而不是所有应用程序加载默认设置,只需执行以下操作:
    # Note: when apps or modules are explicitly passed,
    # the `DEFAULT_SETTINGS_MODULE` var is not required

    from app_defaults import Settings

    settings = Settings(apps=["my_app"])

    # or

    from my_app import defaults
    settings = Settings(modules=[defaults])

    关于python - Django 应用程序默认设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39889529/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com