Django之django-dynamic-preferences

Django之django-dynamic-preferences

django-dynamic-preferences官方文档
动态首选项是经过BSD许可的Django应用,旨在帮助您管理项目设置. 在大多数情况下,一个settings.py文件就足够了,但是在某些情况下,您需要一些更灵活的东西,例如:

每个用户的设置(或者通常来说,每个实例的设置)
设置更改而无需重新启动服务器
对于每个实例的设置,您实际上可以将它们存储在某种配置文件模型中. 但是,这意味着每次您要添加新设置时,都需要向配置文件DB表中添加新列. 不是很有效.

动态首选项允许您以声明的方式注册设置(即首选项). 首选项值在存储到数据库之前先进行序列化,然后在需要时自动反序列化.

使用动态首选项,您可以通过django的管理或自定义表单即时更新设置,而无需重新启动应用程序.

该项目已经过测试,可以在Django> = 1.8的Python 2.7和3.4、3.5和3.6下运行.

理解

比如当你想要对用户进行特殊的设置时,一般都是在数据库用户的表中添加一些字段,当用户进行某些不同的设定,字段便更改,但是当你想要再加一些字段时就比较麻烦,还要重启应用程序等等,django-dynamic-preferences便是处理此类事情的,不仅可以做到对每个用户,每个实例的动态设置,还可以对全局进行动态的设置,而不需要重启应用程序

实现方法

您可以通过django的管理或自定义表单即时更新设置,而无需重新启动应用程序.
意思就是说:你可以在django的后台管理进行即使更新设置,也可以在前端页面上自定义表单进行及时更新设置

特征

  • 设置简单
  • 管理员整合
  • 表格整合
  • 捆绑了全局和每个用户的首选项
  • 如果需要,可以扩展到其他模型(例如,每个站点的首选项,模型可以理解为其它表,也就是model)
  • 与django缓存机制集成以提高性能
  • Django REST框架集成

建立

将此添加到您的settings.INSTALLED_APPS:

INSTALLED_APPS = (
    # ...
    'django.contrib.auth',
    'dynamic_preferences',
    # comment the following line if you don't want to use user preferences
    # 如果不想使用用户首选项,请注释以下行
    'dynamic_preferences.users.apps.UserPreferencesConfig',
)

然后,在数据库中创建丢失的表:

python manage.py migrate dynamic_preferences

settings.TEMPLATES如果要从模板访问首选项,请添加至:

TEMPLATES = [
    {
        # ...
        'OPTIONS': {
            'context_processors': [
                # ...
                'django.template.context_processors.request',
                'dynamic_preferences.processors.global_preferences',
            ],
        },
    },
]

设定值

另外,如果要自定义程序包的行为,请花一些时间查看提供的设置:

# available settings with their default values
DYNAMIC_PREFERENCES = {

    # a python attribute that will be added to model instances with preferences
    #一个python属性,它将被添加到带有首选项的模型实例中
    # override this if the default collide with one of your models attributes/fields
    # 如果默认值与某个模型属性/字段发生冲突,请重写此值
    'MANAGER_ATTRIBUTE': 'preferences',

    # The python module in which registered preferences will be searched within each app
    # 在每个应用程序中搜索已注册首选项的python模块
    'REGISTRY_MODULE': 'dynamic_preferences_registry',

    # Allow quick editing of preferences directly in admin list view
    # 允许快速编辑的首选项直接在管理列表视图
    # WARNING: enabling this feature can cause data corruption if multiple users
    # 警告:如果有多个用户,启用此功能可能导致数据损坏
    # use the same list view at the same time, see https://code.djangoproject.com/ticket/11313
    # 同时使用相同的列表视图,请参见https://code.djangoproject.com/ticket/11313
    'ADMIN_ENABLE_CHANGELIST_FORM': False,

    # Customize how you can access preferences from managers. The default is to
    # 自定义如何从管理器访问首选项。默认值是  '__'
    # separate sections and keys with two underscores. This is probably not a settings you'll
    # want to change, but it's here just in case
    'SECTION_KEY_SEPARATOR': '__',

    # Use this to disable caching of preference. This can be useful to debug things
    # 使用它来禁用首选项的缓存。这对于调试很有用
    'ENABLE_CACHE': True,

    # Use this to disable checking preferences names. This can be useful to debug things
    # 使用它来禁用检查首选项名称。这对于调试很有用
    'VALIDATE_NAMES': True,
}

创建并注册自己的首选项

首先,在您的一个项目应用程序中创建一个dynamic_preferences_registry.py文件。该应用程序必须在中列出settings.INSTALLED_APPS。

让我们在此文件中声明一些首选项:

from dynamic_preferences.types import BooleanPreference, StringPreference
from dynamic_preferences.preferences import Section
from dynamic_preferences.registries import global_preferences_registry
from dynamic_preferences.users.registries import user_preferences_registry

# we create some section objects to link related preferences together
# 我们创建一些section对象来链接相关的首选项

general = Section('general')
discussion = Section('discussion')

# We start with a global preference
# 我们从全局首选项开始
@global_preferences_registry.register
class SiteTitle(StringPreference):
    section = general
    name = 'title'
    default = 'My site'
    required = False

@global_preferences_registry.register
class MaintenanceMode(BooleanPreference):
    name = 'maintenance_mode'
    default = False

# now we declare a per-user preference
# 现在我们声明一个每个用户的首选项
@user_preferences_registry.register
class CommentNotificationsEnabled(BooleanPreference):
    """Do you want to be notified on comment publication ?"""
    section = discussion
    name = 'comment_notifications_enabled'
    default = True

该section属性是一种方便的方式,我习惯将它称之为节部分或节名称,可以将您的首选项保留在不同的节部分中。尽管您完全可以忘记此属性,但是它在诸如admin或表格之类的各种位置用于过滤和分离首选项。如果您有许多不同的首选项,您可能会发现它很有用。该name属性是您偏好的唯一标识符。但是,如果使用不同的节部分,则可以为各种首选项共享相同的名称。

注意:

首选项名称和节名称(如果使用的话)将保留在数据库中,应视为主键。如果由于某种原因想要更新首选项或节名称并保持已保存的首选项同步,则必须编写数据迁移。

检索和更新首选项

您可以通过Manager类似字典的对象获取和更新首选项。全局首选项和每个实例首选项的逻辑几乎完全相同。

from dynamic_preferences.registries import global_preferences_registry

# We instantiate a manager for our global preferences
# 我们为全局首选项实例化一个管理器
global_preferences = global_preferences_registry.manager()

# now, we can use it to retrieve our preferences
# 现在,我们可以用它来检索首选项
# the lookup for a preference has the following form: <section>__<name>
# 查找首选项的形式如下:<section>__<name>
assert global_preferences['general__title'] == 'My site'
# 亦或者是这样
if global_preferences['general__title'] == 'My site':
	业务逻辑
# You can also access section-less preferences
# 您还可以访问无节部分首选项
assert global_preferences['maintenance_mode'] == False

# We can update our preferences values the same way
# 我们可以用同样的方法更新偏好值
global_preferences['maintenance_mode'] = True

对于每个实例(或是每个用户)的首选项,它甚至更加容易。您可以通过preferences属性访问每个实例首选项。

from django.contrib.auth import get_user_model

user = get_user_model().objects.get(username='eliot')

assert user.preferences['discussion__comment_notifications_enabled'] == True

# Disable the notification system
# 当把首选项的值变为False时,便等于说是此用户禁用通知系统
user.preferences['discussion__comment_notifications_enabled'] = False

访问首选项值和设置首选项值时遵循的步骤:

当您访问首选项值(例如通过global_preferences[‘maintenance_mode’])时,动态首选项将遵循以下步骤:

  1. 它检查缓存的值(使用经典的django缓存机制)
  2. 如果找不到缓存键,它将查询数据库中的值
  3. 如果该值在数据库中不存在,则会添加具有默认首选项值的新行,并返回该值。缓存将更新,以避免下次您要检索该值时再次查询数据库。

因此,在最坏的情况下,访问单个首选项值可能会触发最多两个数据库查询。但是,大多数情况下,动态首选项只会命中缓存。

设置首选项值时(例如,通过“ global_preferences [‘maintenance_mode’] = True”),动态首选项将遵循以下步骤:

  1. 从数据库中查询相应的行(1个查询)
  2. 设置新值并将其保存在db中(1个查询)
  3. 缓存已更新。

更新首选项值将始终触发两个数据库查询。

检索首选项的其他方法

管理者还可以使用其他一些方法来检索首选项:

  • manager.all():返回包含所有首选项标识符和值的字典
  • manager.by_name():返回一个包含所有首选项标识符和值的字典。 首选项部分名称(如果有)已从标识符中删除
  • manager.get_by_name(name):仅使用首选项名称返回单个首选项值

附加验证

在某些情况下,您需要为首选项值实施自定义规则,并在这些规则不匹配时引发验证错误。

您可以通过validate在您的首选项类上声明一个方法来实现该行为,如下所示:

from django.forms import ValidationError

# We start with a global preference
@global_preferences_registry.register
class MeaningOfLife(IntegerPreference):
    name = 'meaning_of_life'
    default = 42

    def validate(self, value):
        # ensure the meaning of life is always 42
        if value != 42:
            raise ValidationError('42 only')

在内部,validate方法将作为验证器传递给基础表单字段。

首选项生命周期

如果您从注册表中删除首选项,则不会自动删除相应的数据行。

为了保持数据库干净并删除过时的行,可以使用checkpreferences管理命令。该命令将检查数据库中的所有首选项,确保它们与注册的首选项类匹配,并删除与任何注册的首选项都不匹配的行。

警告:小心运行此命令,因为它可能导致数据丢失。

对于每个用户的首选项,但我们注册了一个用户首选项后,那么默认每个用户实例都有了这个属性,我们可以很方便的取出这个属性进行更改,但是好像关联的是auth_user表,咋整?
目前解决办法两个:
1,使用到django自带的auth_user表
2,就是将首选项绑定到自定义的用户表上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值