記述子プロトコルはうまく動作しますが、解決したい問題が1つあります。これは、サブクラス化され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 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
これまでのところ、とても良い、この作品:使用
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)
そして、モデルクラスです
私は記述を持っていますちょうど期待どおり。
唯一の問題は、フィールドが宣言されるたびにフィールド名を指定する必要があることです。例えばcountry_code_2
フィールドの場合は"country_code_2"
です。
モデルクラスの属性名を取得し、それをフィールドクラスで使用する方法はありますか?
提案を実装した後で更新プログラムを追加しました。これを見ていただけますか? –
'six.with_metaclass()'を正しく使用していないので、基本クラスとして使用する必要があります。 http://stackoverflow.com/questions/18513821/python-metaclass-understanding-the-with-metaclassを参照してください。代わりに、 'six'を使う前にPython 2や3で動作させたいかもしれません:-) –
' six.with_metaclass() 'を' __metaclass__ = BaseModelMeta'に置き換えました。 (私はPython 2を使っています)これは同じエラーを出しています。 –