本文基于 django-constanc

安装

django-constance分为redis存储设置的版本和使用database存储设置的版本,对应的下载方式分别为:

  1. pip install "django-constance[redis]"
  2. pip install "django-constance[database]"

如果确认相关依赖已经安装,直接使用下列命令安装:

  1. pip install django-constance

配置

settings.py文件

  1. # 已安装的Apps
  2. INSTALLED_APPS = [
  3. 'constance',
  4. ...
  5. ]

若使用database存储设置的版本,请使用:

  1. # 已安装的Apps
  2. INSTALLED_APPS = [
  3. 'constance',
  4. 'constance.backends.database',
  5. ...
  6. ]

声明待配置选项:

  1. CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
  2. CONSTANCE_IGNORE_ADMIN_VERSION_CHECK = True
  3. CONSTANCE_ADDITIONAL_FIELDS = {
  4. 'coupon_select': ['django.forms.fields.ChoiceField', {
  5. 'widget': 'django.forms.Select',
  6. 'choices': ((0, "时+分+秒"), (1, "时+分"), (2, "时"), (3, "忽略"))
  7. }],
  8. }
  9. CONSTANCE_CONFIG = {
  10. 'site_name': ('南京诗远启', '网站标题'),
  11. 'site_description': ('南京诗远启', '站点描述'),
  12. 'coupon_fix_code': ('DreamGo', '电子券固定代码'),
  13. 'coupon_time_format': (0, '电子券时间格式', 'coupon_select'),
  14. 'sms_reset_date': (1, '分配短信清零时间'),
  15. }
  16. CONSTANCE_CONFIG_FIELDSETS = {
  17. '站点设置': ('site_name', 'site_description'),
  18. '电子券': ('coupon_fix_code', 'coupon_time_format', ),
  19. '短信': ('sms_reset_date', ),
  20. }

'site_name': ('南京诗远启', '网站标题'), 分别代表 设置变量的名称 默认值 设置变量用途描述(help_text)

'coupon_time_format': (0, '电子券时间格式', 'coupon_select'),前3个变量意义同上,最后的'coupon_select'代表使用自定义选择控件来选择值。

Admin样式

django-constance实现动态设置 - 图1

使用代码获取当前设置值

  1. from constance import config
  2. def set_value(key, value):
  3. """
  4. 更新数据库设置项
  5. :param key: 键名
  6. :param value: 值
  7. :return: 无返回
  8. """
  9. setattr(config, key, value)
  10. def get_value(key):
  11. """
  12. 获取数据库设置项值
  13. :param key: 键名
  14. :return: 键名对应的设置项值
  15. """
  16. return getattr(config, key)

用法:

  1. set_value('site_name', '南京诗远启(修改后)')
  2. get_value('site_name') # 应为'南京诗远启(修改后)'

DjangoRestFramework中使用

utils.py:

  1. from constance import config
  2. from constance.settings import CONFIG
  3. def get_settings(allow_settings):
  4. """
  5. 获取对应settings组成的list
  6. :param allow_settings: 待转义列表
  7. :return: 对应settings组成的list
  8. """
  9. setting_list = []
  10. for key, options in CONFIG.items():
  11. if key in allow_settings:
  12. default, help_text = options[0], options[1]
  13. data = {'key': key, 'default': default, 'help_text': help_text, 'value': get_value(key)}
  14. setting_list.append(data)
  15. return setting_list

views.py:

  1. from rest_framework.viewsets import ViewSet
  2. from rest_framework.response import Response
  3. from .utils import set_value, get_value, CONFIG
  4. class SettingViewSet(ViewSet):
  5. permission_classes = (IsAuthenticated,)
  6. def setting(self, request, allow_settings):
  7. if request.method == 'GET':
  8. return Response(data=get_settings(allow_settings), status=status.HTTP_200_OK)
  9. else:
  10. all_settings = CONFIG.keys()
  11. for key in request.data:
  12. if key in allow_settings and key in all_settings:
  13. value = request.data[key]
  14. set_value(key, '' if value is None else value)
  15. return Response(data=get_settings(allow_settings), status=status.HTTP_200_OK)
  16. def create(self, request):
  17. """
  18. <p>更新设置POST:<code>{'设置Key': 新值}</code>
  19. """
  20. return self.setting(request, CONFIG.keys())
  21. def list(self, request):
  22. """
  23. 返回所有待选设置项
  24. """
  25. return self.setting(request, CONFIG.keys())
  26. @action(methods=['GET', 'POST'], detail=False)
  27. def site(self, request):
  28. """仅允许设置 网站标题、站点描述的接口"""
  29. allow_settings = ['site_name', 'site_description']
  30. return self.setting(request, allow_settings)

固定设置项在Admin中的顺序

为了防止每次打开设置界面设置选项错误,需要使用OrderedDict来保证顺序:

  1. from collections import OrderedDict
  2. SITE_NAME = 'site_name'
  3. SITE_DESCRIPTION = 'site_description'
  4. CONSTANCE_CONFIG = OrderedDict([
  5. (SITE_NAME, ('南京诗远启', '站点名称')),
  6. (SITE_DESCRIPTION, ('南京诗远启', '站点描述')),
  7. ])
  8. CONSTANCE_CONFIG_FIELDSETS = OrderedDict([
  9. ('站点设置', (SITE_NAME, SITE_DESCRIPTION)),
  10. ])

QA

出现没有表的情况

执行:

  1. python manage.py makemigrations constance
  2. python manage.py migrate constance

在makemigrations时就提示表不存在

INSTALLED_APPS中加constance.backends.database,删除使用到constance的地方,makemigrations之后再迁移。

修改权限'constance.change_config'的名称后报错

constance默认提供了一个权限'constance.change_config',但是当修改了该权限的默认权限名称后,会出现一下错误:

  1. django.db.utils.IntegrityError: (1062, "Duplicate entry '2-change_config' for key 'auth_permission_content_type_id_codename_01ab37
  2. 5a_uniq'")

重新浏览代码后发现是在constance/apps.py 29行,写了:

  1. permission, created = Permission.objects.using(using).get_or_create(
  2. name='Can change config',
  3. content_type=content_type,
  4. codename='change_config')

将其修改为:

  1. permission, created = Permission.objects.using(using).get_or_create(
  2. content_type=content_type,
  3. codename='change_config',
  4. defaults={'name': 'Can change config'})

即可解决这个错误,详见issue。 该PR已提交,代码合并成功,在一个正式版本该问题将被解决。

makemigrations constance一直不创建makemigrations文件

Backends->Database

  1. pip install django-constance[database]
  2. CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
  3. INSTALLED_APPS = (
  4. # other apps
  5. 'constance.backends.database',
  6. )
  7. python manage.py migrate database

频繁查询、更新的设置项 使用Cache加快访问速度

  1. # cache配置
  2. CACHES = {
  3. 'default': {
  4. 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
  5. 'LOCATION': 'unique-snowflake',
  6. 'KEY_PREFIX': 'protal',
  7. 'options': {
  8. 'MAX_ENTRIES': 1024,
  9. }
  10. },
  11. 'memcache': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  13. 'LOCATION': '127.0.0.1:11211',
  14. 'KEY_PREFIX': 'protal',
  15. 'options': {
  16. 'MAX_ENTRIES': 1024,
  17. }
  18. },
  19. }
  20. # 设置缓存
  21. CONSTANCE_DATABASE_CACHE_BACKEND = 'memcache'

Illegal mix of collations for operation ' IN '

若在升级项目中遇到mysql报错

  1. Illegal mix of collations for operation ' IN '

需要删除数据库,再次创建 create database database_name character set utf8; 再次导入数据库即可。