使用SettingsMixin¶
SettingsMixin是一个混合类,用于方便地跟用户定义的类进行复合,在定义配置项的时候, 将定义放到lib层,而不是孤立地放在settings.py或配置模块中,再人工进行关联。
定义配置项¶
一个简单的使用例子如下:
from qt4s.service import Channel
from qt4s.conn2 import HttpConn
from testbase.conf import SettingsMixin
class MyChannel(Channel, SettingsMixin):
"""define a pseudo channel
"""
class Settings(object):
MYCHANNEL_URL = "http://www.xxxx.com"
def __init__(self):
self._conn = HttpConn()
def get(self, uri, params):
return self._conn.get(self.settings.MYCHANNEL_URL + uri, params)
MyChannel多重继承了Channel和SettingsMixin,SettingsMixin要求类的内部定义一个Settings类, 这个类定义配置项的规则如下:
- 配置项必须以当前类的名字大写+下划线开头,例如这里的"MYCHANNEL_";
- 配置项的每个字母都必须大写;
- 访问配置项,使用self.settings访问,例如self.settings.MYCHANNEL_URL
重载配置项¶
重载配置项,分为两种情况
派生类重载¶
如果某个SettingsMixin类被继承,那么子类可以访问父类所拥有的配置项,并且可以重载父类的配置项,但是这里重载的方式比较特殊。
因为SettingsMixin要求当前类下必须定义一个嵌套Settings类,并且配置项必须以类名加下划线开头,因此,子类要重载父类的配置项, 通过定义相同后缀的配置项来实现,如下面的DUMMY_A和DUMMYCHILD_A,它们的后缀名都是"A",这样才会生效。
一个具体的例子如下:
from testbase.conf import SettingsMixin
class Dummy(SettingsMixin):
class Settings(object):
DUMMY_A = 0
def print_a(self):
print("DUMMY_A=%s" % self.settings.DUMMY_A)
class DummyChild(Dummy):
class Settings(object):
DUMMYCHILD_A = 2
dummy = Dummy()
assert dummy.settings.DUMMY_A == 0
dummy.print_a()
# DUMMY_A = 0
child = DummyChild()
assert child.settings.DUMMY_A == 2
assert child.settings.DUMMYCHILD_A == 2
child.print_a()
# DUMMY_A = 2
如上,我们看到,在覆盖掉父类的配置项后,在父类的方法中访问的配置项也一样会被重载,这样可以复用父类的一些配置项,并根据需要进行重载。
全局配置项重载¶
SettingsMixin定义的配置项还可以被全局配置项重载,并且全局配置项的优先级最高。我们仍然用上面的Dummy和DummyChild来说明问题。
settings.py:
DUMMYCHILD_A = 3
xxxxcase.py:
dummy = Dummy()
assert dummy.settings.DUMMY_A == 0
dummy.print_a()
# DUMMY_A = 0
child = DummyChild()
assert child.settings.DUMMY_A == 3
assert child.settings.DUMMYCHILD_A == 3
child.print_a()
# DUMMY_A = 3
可以看到,即使子类重载了DUMMY_A的值为2,但是仍然可以在settings.py中已更高的优先级将其修改。
警告
框架在SettingsMixin定义的某个配置项被子类重载后,是不允许再在settings.py中去重载该配置项的, 即:如果我们在settings.py中添加DUMMY_A = 5,框架会提示错误,要求用户去重载DUMMYCHILD_A,而不是DUMMY_A。 这样可以防止使用配置项在派生类之间冲突,并且简化配置项的设置。