GAE/Goのblobstoreを使ったCSVアップロードとCSV読み込み

経緯

別のソースコードでCSVアップロードを試していたら、コードの書きかたが正しくないか、github.com/gorilla/muxの使い方に問題があって、CSVデータをテキストでブラウザーに表示するはずがダウンロードになってしまい問題が解決できませんでした。

対応

github.com/gorilla/muxなどや他のソースコードを含めず、単純なCSVファイルをアップロードし、それをブラウザーでテキストとして表示するサンプルを書きました。

これはyomusu/csvblob.goをフォークしました。 context型やappengineのインポートを変更していますが、基本処理はyomusuさんのコード其のままです。

このソースコードでdev_appserver.py上で問題なく動作しました。

index.yamlが自動生成されて動かなくなったdev_appserver.pyを元通りにする

kindやAncestorを試しているうちに動かなくなった

開発途中でいきなりdev_appserver.pyが正常に動作しなくなり以下のログを出力しました。状況としては、

  • dev_appserver.pyは起動問題なし
  • localhost:8000で、datastoreをブラウザから見ようとすると、以下と同様なエラーがブラウザーに表示
  • アプリの登録処理ができない

原因は、index.yamlの自動生成

自動でindex.yamlが生成されていた事でした。このファイルは、独自にインデックスを用意する場合に使うのと、開発サーバーが自動生成したインデックスをここに書き込んでくれるようです。

https://cloud.google.com/appengine/docs/standard/go/config/indexconfig

DatastoreのkindやAncestorを試しているうちにこのindex.yamlが作られたようです。

対応方法は、不要なインデックスをindex.yamlから削除

j上記のコメントの後に、自動生成されたインデックスが書かれていますがコメントアウト、または削除しdev_appserve.pyを起動し直せばよいです。inde.yamlファイル自体を削除すると、インデックスが必要というエラーが別に発生しました。

 

その他

この問題を調べているうちに、datastoreの保存先やクリアの仕方が分かりましたのでメモを残しておきます。

clear_datastore=yesでdatastore削除

clear_datastore=yesとclear_search_indexes起動オプションでデータ削除できることが分かりましたが解決できませんでした。

物理的に削除

上記オプションでdev_appserver.pyを起動すると、以下のようappengine.Noneがあり、これを削除すればよいと分かりました。

https://stackoverflow.com/questions/25831141/google-app-engine-datastore-storage-default-path

削除したけれど解決できませんでした。

Ctrl+Cで終了してみると以下のようにpending transactionsと読み取れるのでこの失敗したデータ登録がどこかで保持されているので、データベースを削除しても実行されているようです。

 

 

 

html/templateでrangeでindexを使い別のスライスを参照する方法

Go言語のhtml/templateは、スライスやMapオブジェクトに対して{{range $index, $element := xxxxx}}のような記法でインデックスが使えます。

例えば、[]Userと[]Keyという対になったスライスが2つある場合、UserをRangeアクションでループ処理している間に、Key[i]のようにして別のスライスにアクセスしたい場合があります。(本当に汎用的な解決策はおそらくzip関数。)

このような場合は、以下の記述で[]Userと[]Keyのそれぞれの要素にアクセスできます。html/templateでは、{{range $i, $user := users}}でインデックスと要素にアクセスできるため{{$i}} {{$user}}で表示しています。またrangeスコープないなので、ドット{{.}}は、現在のuser要素を表示します。最後に、通常のプログラミング言語でKeys[i]やUser[i]のように要素取得するのを、{{index $.Keys $i}}で行っています。index関数の第一引数が、Keysスライス、第二引数がインデックスという意味です。

また、$.Keysがポイントで、rangeスコープ内で、ドットを指定するとuser要素になりますが、$.とすることでグローバルを参照します。

 

 

結果