The descriptor protocol works fine, but I still have one problem that I would like to solve.
I have a handle:
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")
These are subclasses:
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)
And then the model class is used:
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
So far, so good, it works as expected.
The only problem I have here is that we must provide the field name with every field declaration. for example "country_code_2"
for a field country_code_2
.
How can I get the attribute name of a model class and use it in a field class?