dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

[GAE] Repeated Property について

ちょいメモ。
ndb の "Repeated Property" について、仕様として気になることをちょっと調べてまとめてみました。

はじめに (Repeated Propertyって?)

ndb のプロパティに repeated=True をつけたものを Repeated Property といい、
プロパティに配列を渡して値を複数保存することができます。

class MyModel(ndb.Model):
    items = ndb.StringProperty(repeated=True)

key = ndb.Key(MyModel, 'test')
obj = MyModel(key=key, items=['item1', 'item2'])
obj.put()

print obj

上記の結果は

MyModel(key=Key('MyModel', 'test'), items=[u'item1', u'item2'])

となります。また、

key = ndb.Key(MyModel, 'test')
obj = key.get()
obj.items.append('new_item')

obj.put()

のように、通常の python の list と同じように扱うことができます。

気になったこと

  1. 初期値は None
    • 初期値というか、何も指定せずにエンティティを保存した時、次にそれを取り出したら None が入ってるんでしょうか。
  2. Noneを指定して保存するとどうなるのか?
    • 1とも関連しますが、今度は明示的に None を指定して保存した場合、次に取り出したらどうなるか。
  3. set を渡しても保存できるのか?

順番に試してみます。

なお、以下のコードは全部開発サーバーのコンソール(http://localhost:8000/console) で試してます。

1. 初期値は None ?

実行したコード

class MyModel(ndb.Model):
    item = ndb.StringProperty()
    items = ndb.StringProperty(repeated=True)

key = ndb.Key(MyModel, 'test')
obj = MyModel(key=key)
print 'item: %r' % obj.item
print 'items: %r' % obj.items
obj.put()

obj = key.get()
print 'item: %r' % obj.item
print 'items: %r' % obj.items

実行結果

item: None
items: []
item: None
items: []

結論

Repeated Property は何も指定しないと [] (空のlist) がセットされる。

2. Noneを指定して保存するとどうなるのか?

実行したコード

class MyModel(ndb.Model):
    item = ndb.StringProperty()
    items = ndb.StringProperty(repeated=True)

key = ndb.Key(MyModel, 'test')
obj = MyModel(key=key)
obj.items = None
obj.put()

obj = key.get()
print 'items: %r' % obj.items

実行結果

なんかエラーでた。

Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/devappserver2/python/request_handler.py", line 225, in handle_interactive_request
    exec(compiled_code, self._command_globals)
  File "<string>", line 30, in <module>
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 1363, in __set__
    self._set_value(entity, value)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 1104, in _set_value
    (value,))
BadValueError: Expected list or tuple, got None

結論

そもそも保存ができない。BadValueError になる。

3. set を渡しても保存できるのか?

実行したコード

class MyModel(ndb.Model):
    item = ndb.StringProperty()
    items = ndb.StringProperty(repeated=True)

key = ndb.Key(MyModel, 'test')
obj = MyModel(key=key)
obj.items = set(['1', '2'])
obj.put()

obj = key.get()
print 'items: %r' % obj.items

実行結果

items: [u'1', u'2']

結論

OK。
念のため tuple も試したけど問題ありませんでした。

まとめ

  1. 初期値は None
    • [](空の list) がセットされる
  2. Noneを指定して保存するとどうなるのか?
  3. そもそも保存ができない。BadValueError になる
  4. set を渡しても保存できるのか?
    • set も tuple もOK