Django の Storage よくわかんないけど無理やり握りつぶして粉砕した話(から、できるだけ例外処理しないロジックをつくりましょうの話)
Django の Storage ってのがあんまりよくわかっていない
とりあえず公式ドキュメントは以下
カスタムのストレージシステムを作成する — Django v1.0 documentation
基本的にはなんかこう OS のファイルシステムみたいな感じにさわれる?まあストレージっていうくらいだからどこかに保存して、 open してなにかこうファイルをよしなにするためのシステムって感じなのは触っていてわかった感じ。Storage には open とか listdir とか copy とかファイルシステムを扱う上での便利メソッドが生えている。
空文字を copy できないっぽい
具体的には擬似コード的にはこんな感じ
copy_settings = [] for hoge in HogeModel.objects.all(): # これ、 append のほうがいいきがするけどどうなんだろう…… copy_settings += get_path() # コピー for src, dst in copy_settings: try: # Storage のインスタンス(だとおもう) src_storage.copy( src, dst, # これも Storage のインスタンス(だとおもう) to_storage=dst_storage, ) except IOError: pass
こんな感じであるストレージからあるストレージへコピーするという処理をしていた。ただそのときいろいろ処理をしていた関係で空文字列 u'' が紛れ込んでしまった。空文字だと IOError で落ちるのだ。なのでとりえあず潰した。ああ、綺麗じゃない。行儀が良くない。というかいいロジックな気がしない。例外を raise なり return して吐かないのはすごい美しくない気がするけど、今回はそうもいってられなくて無理やり潰してしまった。
オチ
そんなものはありません。
ストレージまわりむずかしいなぁってのもあるけど、そもそもその内部ロジック(この場合 get_path())が美しくない。もっといい感じにしたかったけど、なんかうまくいかなくて、とりあえず無理やり実装した。はぁ。いいのかなぁ。
ってかいたんだけど!!!!
別にその get_path()のロジック自体である状態の時はスキップするようにしたから別に try except で潰さなくてよくなりました。まる。擬似コード的残すとこんな感じ。
# なんか for でまわすんよ for hoge in HogeModel.objects.all(): # なんかそのインスタンスの Path をいれるんよ path = hoge.path # その path を元にしてパスの名前をつくるんよ path_name = generate_path_name(path) # このとき コピー対象にならない path_name を None で返してしまえばループから抜け出せるんよ if not path_name: continue ...
ね、簡単でしょう(ニッコリ)
Django の South で migrate したときに south.exceptions.GhostMigrations
migrate がなんかうまくいかない
コマンドは普通
python manage.py migrate --setting=settings...
例外がでた。同じ症状のが StackOverFlow にあったのではる
API Only - Stack Exchange
Traceback (most recent call last): File "manage.py", line 14, in <module> execute_manager(settings) File "/home/username/webapps/myproject/lib/python2.6/django/core/management/__init__.py", line 438, in execute_manager utility.execute() File "/home/username/webapps/myproject/lib/python2.6/django/core/management/__init__.py", line 379, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/home/username/webapps/myproject/lib/python2.6/django/core/management/base.py", line 191, in run_from_argv self.execute(*args, **options.__dict__) File "/home/username/webapps/myproject/lib/python2.6/django/core/management/base.py", line 220, in execute output = self.handle(*args, **options) File "/home/username/lib/python2.6/South-0.7.3-py2.6.egg/south/management/commands/migrate.py", line 105, in handle ignore_ghosts = ignore_ghosts, File "/home/username/lib/python2.6/South-0.7.3-py2.6.egg/south/migration/__init__.py", line 171, in migrate_app applied = check_migration_histories(applied, delete_ghosts, ignore_ghosts) File "/home/username/lib/python2.6/South-0.7.3-py2.6.egg/south/migration/__init__.py", line 88, in check_migration_histories raise exceptions.GhostMigrations(ghosts) south.exceptions.GhostMigrations: ! These migrations are in the database but not on disk: <bodyguard: 0002_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie> <bodyguard: 0003_auto__del_field_asset_is_reserved__add_field_asset_is_assigned> ! I'm not trusting myself; either fix this yourself by fiddling ! with the south_migrationhistory table, or pass --delete-ghost-migrations ! to South to have it delete ALL of these records (this may not be good).
これってなにかというと、要は MySQL とかに south_migrationhistory ってテーブルがあって、それを migration のたびにレコードを更新しているんだけどその database にはあって disk = migration file がないよって話。なんらかのかたちでこのエラーに遭遇したら、とりあえず警告にあるとおりに --delete-ghost-migrations してやれば解決する
python manage.py migrate --settings=settings... --delete-ghost-migrations
South はマジ便利、だけど銀の弾丸ではない
気をつけないといろいろハマりがち