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 まるごと削除できるらしい。
記事が長くなったので 次回 に続きます。