Вот решение, которое позволяет вам обходить любые дескрипторы, определенные в классе:
class BypassableDescriptor(object):
pass
class String(BypassableDescriptor):
def __init__(self, value=None):
if value:
self.value = str(value)
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = str(value)
def to_db(self):
return {'type': 'string', 'value': self.value}
class Integer(BypassableDescriptor):
def __init__(self, value=None):
if value:
self.value = str(value)
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = int(value)
def to_db(self):
return {'type': 'integer', 'value': self.value}
class BypassDescriptor(object):
def __init__(self, descriptor):
self.descriptor = descriptor
def __getattr__(self, name):
return getattr(self.descriptor, name)
class AllowBypassableDescriptors(type):
def __new__(cls, name, bases, members):
new_members = {}
for name, value in members.iteritems():
if isinstance(value, BypassableDescriptor):
new_members['real_' + name] = BypassDescriptor(value)
members.update(new_members)
return type.__new__(cls, name, bases, members)
class Example(object):
__metaclass__ = AllowBypassableDescriptors
name = String()
age = Integer()
def __init__(self,name,age):
self.name = name
self.age = age
def save(self):
data = dict(name = self.real_name.to_db(), age = self.real_age.to_db())
Обратите внимание, что это не идеально - вам всегда придется вызывать real_fieldname.method()
вместо fieldname.method()
, и выВам придется использовать метакласс AllowBypassableDescriptors для всех ваших классов, которым требуется доступ к этому полю.Опять же, это довольно совместимое решение, позволяющее избежать мартовских исправлений объекта, обернутого дескриптором.
Тем не менее, я не уверен, что дескрипторы - лучшее решение для того, что вы пытаетесь сделатьв базу данных?).