Datastoreにデータを格納するモデルを作成してテストしていると、データモデルの動作がおかしくなることがある。この場合、AppEngine 管理画面の Datastore Viewer で、データ確認及び削除が可能だ。
しかし異常データによっては、Datastore Viewer がエラーで開くことができないことがある。例えば、おかしなデータがあるKind を選択すると下の画面になる。
Error (500)
仕方ないのでプログラムを作成してデータ削除を試みる。
# -*- coding: utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp.util import run_wsgi_app
class DeleteEntities(webapp.RequestHandler):
def display(self, finished, counter, total):
wait = 10
self.response.headers['Content-Type'] = 'text/html'
write = self.response.out.write
write( '<html>'
'<head>' )
if not finished:
url = self.request.url.split('?')[0]
write( '<meta http-equiv="refresh" content="%d;url=%s?total=%d">' % (wait, url, total))
write( '</head>'
'<body>')
if not finished:
write( '%d deteted / total %d deleted <br><br>' % (counter,total))
write( 'Wait %d seconds.' % wait)
else:
write( 'total %d deleted <br><br>' % total)
write( 'Finished.')
write( '</body>'
'</html>' )
def get(self) :
limit = 10
q = db.GqlQuery("SELECT * FROM UserData")
results = q.fetch(limit)
counter = len(results)
total = self.request.get_range("total") + counter
db.delete(results)
if counter == limit:
self.display(False, counter, total)
else:
self.display(True, counter, total)
def main():
application = webapp.WSGIApplication(
[ ('/admin/DeleteEntities', DeleteEntities) ], debug=True)
run_wsgi_app(application)
if __name__ == "__main__":
main()
29行目の db.GqlQuery のパラメーターを変えれば他の Kind にも対応可能だ。次のサイト記事を参考に、上記の削除プログラムを作成した(ありがとうございます)。
参考 : Object Design Blog - Google App Engine データストア上のデータをまとめて消す方法
しかし残念ながら、Datastore Viewer でエラーが出ていたKindに対してプログラムを実行すると、次のエラーが出力される。
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 1833, in fetch raw = raw_query.Get(limit, offset, config=config) File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 1352, in Get batch = batcher.next_batch(limit) File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_query.py", line 1105, in next_batch batch = self.__next_batch.get_result() File "/base/python_runtime/python_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 534, in get_result return self.__get_result_hook(self) File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_query.py", line 1028, in __query_result_hook for result in query_result.result_list()] File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 110, in pb_to_query_result return self.pb_to_entity(pb) File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 205, in pb_to_entity return Entity._FromPb(pb) File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 844, in _FromPb value = datastore_types.FromPropertyPb(prop) File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore_types.py", line 1628, in FromPropertyPb federated_identity=federated_identity) File "/base/python_runtime/python_lib/versions/1/google/appengine/api/users.py", line 106, in __init__ raise UserNotFoundErrorクエリーやGQLの削除は、削除動作前にデータを読み出している。このため、バリデーションが原因で削除できないという問題が発生しているようだ。
では問題のデータはどうやって削除できるのか・・・・・・?。
管理コンソールにある DatastoreAdmin というツールで Kind まるごと削除できるらしい。
記事が長くなったので 次回 に続きます。