null オブジェクトは直接、データストアに入らない
Python では Null という便利なクラスが提唱されています。
# # null.py # class Null(object): """ Null objects always and reliably "do nothing." """ # optional optimization: ensure only one instance per subclass # (essentially just to save memory, no functional difference) def __new__(cls, *args, **kwargs): if '_inst' not in vars(cls): cls._inst = super(Null, cls).__new__(cls, *args, **kwargs) return cls._inst def __init__(self, *args, **kwargs): pass def __call__(self, *args, **kwargs): return self def __repr__(self): return "Null( )" def __nonzero__(self): return False def __getattr__(self, name): return self def __setattr__(self, name, value): return self def __delattr__(self, name): return self
AppEngine のデータストアは、null オブジェクトを None として扱ってくれません。
従って、以下のプログラムでは BadValueError: Unsupported type for property name:
class TestModel(db.Model): name = db.StringProperty() from null import Null def store(data): data = data or Null() entity = TestModel(name=data.name) entity.put()
- 解決策 1 : or None を使う
def store(data): data = data or Null() entity = TestModel(name=data.name or None) entity.put()
- 解決策 2 : Property クラスの validator で対処する
StringProperty のコンストラクタ引数で別の validator をセットするやり方もありますが、型チェックは継承したいので、StringProperty を継承したクラスを適当に作って、valudate メソッドをオーバーライドします。
def validate_null(value): # 引数 |value| が Null なら None を返す if isinstance(value, Null): # Null -> None return None return value class StringProperty(db.StringProperty): ''' Null オブジェクトを None として扱う StringProperty クラス ''' def validate(self, value): v = validate_null(value) return super(StringProperty, self).validate(v) class TestModel(db.Model): name = NullStringProperty() from null import Null def store(data): data = data or Null() entity = TestModel(name=data.name) entity.put()
validate(value)
プロパティ用の完全な検証ルーチン。value が有効な場合、そのままの値、または必要な型に適合させた値を返します。それ以外の場合、対応する例外を返します。
- 注)ListProperty の validate() は None でなく、空のリスト [] を返すようにする。
class ListProperty(db.ListProperty): def validate(self, value): v = value if value else [] return super(ListProperty, self).validate(v)