Skip to main content

一个一致的、用户友好的解决方案,用于在 Django 包、可重用应用程序或框架中添加特定于应用程序的设置。

项目描述

Django 齿轮 构建状态 派皮版本 代码覆盖率

什么是 django-cogwheels?

django-cogwheels的目的是创建一个标准化的、经过良好测试的方法,允许应用程序的用户通过覆盖项目的 Django 设置中的内容来覆盖默认行为。

还有其他应用程序试图解决这个问题,但对我来说,创建一个可以很好地满足弃用设置的解决方案很重要,因为这是我发现自己必须在我维护的应用程序中经常做的事情。对我来说,创造一些东西也很重要:

  • 超级容易设置

  • 正确考虑不同的受众(“应用开发者”和“应用用户”)

  • 适用于 100 个应用程序设置和 5 个应用程序设置一样好

  • 仅在绝对必要时使事情变得复杂

为您的用户提供他们应得的灵活性,并允许他们:

  • 覆盖基本的 Python 类型值,例如:字符串、整数、布尔值、小数和浮点数。

  • 覆盖结构化的 Python 类型值,例如:列表、元组和字典。

  • 使用自定义 Django 模型代替您提供的模型。

  • 使用自定义 python 类、对象或整个模块来代替您提供的那些。

应用开发者的福音!

  • 一种稳定的、记录在案的、标准化的方法,用于实施可覆盖的特定于应用程序的设置。

  • 清楚地定义和传达应用设置的弃用状态,让您可以灵活地重命名、替换或标记设置以在项目的生命周期中移除。使用旧设置名称定义的用户覆盖仍然可供您使用,允许您在弃用期间继续支持它们。

  • 当为模型、模块或其他可覆盖对象设置提供的默认值无效时,有用、一致的错误消息。

  • 缓存导入以快速访问模型、模块和其他可导入的 python 对象。

  • 与 Django 的测试框架配合得很好(订阅 Django 的setting_changed信号,以便在使用override_settings时清除缓存的值)。

对应用程序用户有好处!

  • 当它们的模型、类、方法或模块覆盖设置格式不正确或无法导入时,有用、一致的错误消息。

  • 当它们覆盖已重命名、替换或标记为删除的设置时,会发出有用、一致的弃用警告。

快速入门指南

  1. 使用 pip 安装包:

    pip install django-cogwheels
  2. cd进入项目的根应用程序目录:

    cd your-django-project/yourproject/
  3. 使用 cogwheels Django 应用模板创建一个conf应用:

    django-admin.py startapp conf --template=https://github.com/ababic/cogwheels-conf-app/zipball/master
  4. 打开yourproject/conf/defaults.py,并添加您的设置值,如下所示:

    # You can add settings for any type of value
    MAX_ITEMS_PER_ORDER = 5
    
    # For settings that refer to models, use a string in the format 'app_name.Model'
    ORDER_ITEM_MODEL = 'yourproject.SimpleOrderItem'
    
    # For settings that refer to a python module, use an 'import path' string, like so:
    DISCOUNTS_BACKEND = 'yourproject.discount_backends.simple'
    
    # For settings that refer to classes, methods, or other python objects from a
    # python module, use an 'object import path' string, like so:
    ORDER_FORM_CLASS = 'yourproject.forms.OrderForm'
  5. 要在您的应用程序中使用设置值,只需导入设置助手,并将相关设置作为属性引用,如下所示:

    >>> from yourproject.conf import settings
    
    >>> settings.MAX_ITEMS_PER_ORDER
    5
    
    >>> settings.ORDER_ITEM_MODEL
    'yourproject.SimpleOrderItem'
    
    >>> settings.DISCOUNTS_BACKEND
    'yourproject.discount_backends.simple'
    
    >>> settings.ORDER_FORM_CLASS
    'yourproject.forms.OrderForm'
  6. 对于引用 Django 模型的设置,您可以使用设置助手的特殊模型属性来访问模型类本身,而不仅仅是字符串值。例如:

    >>> from yourproject.conf import settings
    
    >>> model = settings.models.ORDER_ITEM_MODEL
    yourproject.models.SimpleOrderItem
    
    >>> obj = model(id=1, product='test product', quantity=15)
    >>> obj.save()
    
    >>> print(model.objects.all())
    <QuerySet [<SimpleOrderItem: SimpleOrderItem object (1)>]>

    在幕后,调用 Django 的django.apps.apps.get_model()方法,并将结果缓存起来,以便快速有效地处理对同一模型的重复请求。

  7. 对于引用 python 模块的设置,您可以使用设置助手的特殊模块属性来访问模块本身,而不是导入路径字符串:

    >>> from yourproject.conf import settings
    
    >>> module = settings.modules.DISCOUNTS_BACKEND
    <module 'yourproject.discount_backends.simple' from '/system/path/to/your-django-project/yourproject/discount_backends/simple.py'>

    在后台,python 的importlib.import_module()方法被调用,结果被缓存,以便快速有效地处理对同一模块的重复请求。

  8. 对于引用类、函数或其他可导入 python 对象的设置,您可以使用设置助手的特殊对象属性来访问这些对象,而不是导入路径字符串:

    >>> from yourproject.conf import settings
    
    >>> form_class = settings.objects.ORDER_FORM_CLASS
    yourproject.formsOrderForm
    
    >>> form = form_class(data={})
    >>> form.is_valid()
    False

    在后台,python 的importlib.import_module()方法被调用,结果被缓存,以便快速有效地处理对同一对象的重复请求。

  9. 您的应用程序的用户现在可以通过向其项目的 Django 设置模块添加替代值来覆盖任何默认值。例如:

    # userproject/settings/base.py
    
    YOURAPP_MAX_ITEMS_PER_ORDER = 2
    
    YOURAPP_ORDER_ITEM_MODEL = 'userproject_orders.CustomOrderItem'
    
    YOURAPP_DISCOUNTS_BACKEND = 'userproject.discounts.custom_discount_backend'
    
    YOURAPP_ORDER_FORM_CLASS = 'userproject.orders.forms.CustomOrderForm'
  10. 你可能注意到上面的变量名都以YOURAPP_为前缀。此前缀因您的应用程序而异,具体取决于包名称。

    这种设置的“命名空间”很重要。它不仅可以帮助您的应用用户记住他们的覆盖设置适用于哪个应用,而且还有助于防止应用之间的设置名称冲突。

    您可以通过执行以下操作找出您的应用程序的前缀是什么:

    >>> from yourproject.conf import settings
    >>> settings.get_prefix()
    'YOURPROJECT_'

    您可以通过在设置助手类上设置前缀属性来将此前缀更改为您喜欢的任何内容,如下所示:

    # yourapp/conf/settings.py
    
    class MyAppSettingsHelper(BaseAppSettingsHelper):
        prefix = 'CUSTOM'  # No need for a trailing underscore here
    >>> from yourproject.conf import settings
    >>> settings.get_prefix()
    'CUSTOM_'

经常问的问题

1. 有没有我可以查看的django-cogwheels示例实现?

肯定的事。

wagtailmenus使用齿轮来管理它的应用程序设置。见: https ://github.com/rkhleics/wagtailmenus/tree/master/wagtailmenus

您可能还想查看cogwheels 本身中 的测试应用程序,其中包括许多示例: https ://github.com/ababic/django-cogwheels/tree/master/cogwheels/tests

2. defaults.pysettings.py是否必须存在于conf应用程序中?

不,这只是一个建议。每个人对如何构建项目都有自己的偏好,这一切都很好。只要您将defaults.pysettings.py保存在同一个目录中,开箱即用就可以正常工作。

如果你想让defaults.pysettings.py放在不同的地方,cogwheels也支持。但是,您必须在设置助手类上设置defaults_path属性,以便它知道在哪里可以找到默认值。例如:

# yourapp/some_directory/settings.py

class MyAppSettingsHelper(BaseAppSettingsHelper):
    defaults_path = 'yourapp.some_other_place.defaults'

3. 你提到支持设置弃用。这是如何运作的?

不久将添加更完整的文档。同时,如果您对弃用定义的外观感到好奇,您可能需要查看测试应用程序的设置助手定义:https ://github.com/ababic/django-cogwheels/blob/master/cogwheels/tests /conf/settings.py

4.如何为某些设置指定验证规则?

cogwheels执行的唯一验证是设置应该引用 Django 模型和其他可导入项的值,并且仅当您在代码中使用settings.models.SETTING_NAMEsettings.modules.SETTING_NAMEsettings.objects.SETTING_NAME时才会触发此验证导入和访问对象。

目前无法配置 cogwheels 以将验证应用于其他设置值。

我确实打算在未来的版本中支持这样的事情,但我不能就何时做出任何承诺。

如果这让您望而却步,请记住,开发人员故意使用不适当的覆盖值进行设置不符合任何人的利益。只要您的文档充分解释了预期值的规则/边界,问题就应该非常罕见。

5. settings.py中的最后一行是关于什么的?

啊,是的。sys.modules[__ name__ ] = MyAppSettingsHelper()位。我知道一些开发人员可能会认为这很脏/hacky/unpythonic/whatever。我不得不承认,我也有一段时间不确定。

我同意看到这个代码在使用中有点“不寻常”。也许是因为它在很多情况下并不是特别有用,或者是因为错误地使用这些功能可能会以奇怪的、难以调试的方式破坏事物。但是,对这种 hack 的支持不会无处不在,而且在cogwheels的情况下,它很有用,因为它消除了在__init__.py中实例化事物的需要(出于多种原因,我不喜欢它)。

如果你还是不放心,或许Guido van Rossum(Python创始人)可以让你放心? https://mail.python.org/pipermail/python-ideas/2012-May/014969.html

兼容性

当前版本已通过以下兼容性测试:

  • Django 版本 1.11 到 2.2

  • Python 版本 3.4 到 3.8

下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

django-cogwheels-0.3.tar.gz (31.2 kB 查看哈希)

已上传 source

内置分布

django_cogwheels-0.3-py3-none-any.whl (35.2 kB 查看哈希

已上传 py3