TL;DR
実行環境のロケールが、 "C" 等の UTF-8 でないロケールに設定されているからではないでしょうか。
もしロケールが原因なのであれば、 Ubuntu を御使いなら language-pack-ja
等のパッケージでロケールをインストールした上で LANG=ja_JP.UTF-8 ./manage.py runserver
等として UTF-8 のロケールを指定してサーバを起動すれば問題が解決できる可能性があります。
原因の考察
django-import-export
パッケージのコード中、当該メッセージ "Imported file has a wrong encoding" を出力し得るのは以下の個所と見受けられます。
https://github.com/django-import-export/django-import-export/blob/7645954f241aa7f042e9ed7871482f352927097c/import_export/admin.py#L267-L273
try:
data = tmp_storage.read(input_format.get_read_mode())
if not input_format.is_binary() and self.from_encoding:
data = force_text(data, self.from_encoding)
dataset = input_format.create_dataset(data)
except UnicodeDecodeError as e:
return HttpResponse(_(u"<h1>Imported file has a wrong encoding: %s</h1>" % e))
ここでは force_text()
を使っていますので、そこで変換に失敗している可能性もありますが、指定されている self.from_encoding
はデフォルトで UTF-8 のようなので、問題にはならずに済みそうです。
それよりももう一か所、怪しいのは直前の tmp_storage.read()
の呼び出しの中身です。
https://github.com/django-import-export/django-import-export/blob/master/import_export/tmp_storages.py#L27-L43
class TempFolderStorage(BaseStorage):
def open(self, mode='r'):
if self.name:
return open(self.get_full_path(), mode)
else:
tmp_file = tempfile.NamedTemporaryFile(delete=False)
self.name = tmp_file.name
return tmp_file
def read(self, mode='r'):
with self.open(mode=mode) as file:
return file.read()
御覧の通り、 open()
でファイルを開くときに、テキストモードで開いているのに encoding
キーワード引数の指定がありません。この場合 Python 3 では、 実行環境のシステムで指定されたロケールに基づいてエンコーディングを推測し、自動的にデコードを行う 仕様となっています。恐らくここでロケールが適切でないため、 UTF-8 であると推測できずに ASCII で開こうとしてしまっているのではないでしょうか。
※ from_encoding
という設定がありながらファイルを開く段階でロケールに依存して失敗するという話なので、 django-import-export
のバグと言えそうです
解決方法
以上より、ロケール設定への依存が原因だと仮定した場合、解決方法は 3 通りくらいあるかと思います。
ja_JP.UTF-8
等の UTF-8 ロケールをインストールし、システムのデフォルトに設定する
django-import-export
のコードを修正し、 open()
時に encoding
キーワード引数を適切に指定する
- Python がシステムのロケールからエンコーディングを推測する
locale.getpreferredencoding()
関数を hack する (検索してみてください)
1 が楽かとは思いますが、正攻法なのは 2 でしょうね。但し、今後のパッケージアップデートを考えると、修正した内容を pull request で送って merge してもらいたいという話もあり、コストは高いです。 3 はお勧めしません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/16 09:45