Протокол дескриптора работает нормально, но у меня все еще есть одна проблема, которую я хотел бы решить.Как получить имя атрибута при работе с протоколом дескриптора в Python?
У меня есть дескриптор:
class Field(object):
def __init__(self, type_, name, value=None, required=False):
self.type = type_
self.name = "_" + name
self.required = required
self._value = value
def __get__(self, instance, owner):
return getattr(instance, self.name, self.value)
def __set__(self, instance, value):
if value:
self._check(value)
setattr(instance, self.name, value)
else:
setattr(instance, self.name, None)
def __delete__(self, instance):
raise AttributeError("Can't delete attribute")
@property
def value(self):
return self._value
@value.setter
def value(self, value):
self._value = value if value else self.type()
@property
def _types(self):
raise NotImplementedError
def _check(self, value):
if not isinstance(value, tuple(self._types)):
raise TypeError("This is bad")
Это подклассы:
class CharField(Field):
def __init__(self, name, value=None, min_length=0, max_length=0, strip=False):
super(CharField, self).__init__(unicode, name, value=value)
self.min_length = min_length
self.max_length = max_length
self.strip = strip
@property
def _types(self):
return [unicode, str]
def __set__(self, instance, value):
if self.strip:
value = value.strip()
super(CharField, self).__set__(instance, value)
А затем используется модель класса:
class Country(BaseModel):
name = CharField("name")
country_code_2 = CharField("country_code_2", min_length=2, max_length=2)
country_code_3 = CharField("country_code_3", min_length=3, max_length=3)
def __init__(self, name, country_code_2, country_code_3):
self.name = name
self.country_code_2 = country_code_2
self.country_code_3 = country_code_3
До сих пор, так хорошо, это работает как и ожидалось.
Единственная проблема, которую я имею здесь, заключается в том, что мы должны указывать имя поля при каждом объявлении поля. например "country_code_2"
для поля country_code_2
.
Как можно получить имя атрибута класса модели и использовать его в полевом классе?
Я добавил обновление после реализации ваших предложений. Не могли бы вы взглянуть на это? –
Вы не используете 'six.with_metaclass()' правильно, он должен использоваться как базовый класс. См. Http://stackoverflow.com/questions/18513821/python-metaclass-understanding-the-with-metaclass. Вместо этого вы можете начать с того, чтобы заставить его работать только с Python 2 или 3 перед использованием 'six' :-) –
Я заменяю' six.with_metaclass() 'на' __metaclass__ = BaseModelMeta'. (Я использую Python 2) Это дает ту же ошибку. –