Djangoでフォームで受け取った複数のファイルを、パスワード付きZIPで固めてmodelに保存したかった。
Pythonの標準モジュールzipfileではpass付きを展開はできても、作成はできないのでpyminizipを使う。
ファイル名と、中身を別々に渡せれば一時ファイルでもいいんだけど、pyminizipにはファイルパスのリストを渡す必要がある。
その際、一時ファイルを使ってしまうと、ファイル名がランダム文字列になってしまうので、フォームから送られてきたファイル名を維持するために一時ディレクトリを使い、その中にアップロードされた名前でファイルを作成する。
with文を使ってるので、closeとかの処理が省けるし、ブロックを抜けた時にすぐ消えてくれるので気持ちがいい。
コードは実コードをサンプル用に手を入れてるので動かなさそう。
views.py
import os import pyminizip from tempfile import TemporaryDirectory from .models import ZipFile def index(request): if request.method == 'POST': form = MailForm(request.POST, request.FILES) if form.is_valid(): # djangoのフォームからファイル取り出す received_files = request.FILES.getlist('file_field') password = "pass" temp_file_list = [] with TemporaryDirectory() as temp_dir: # ZIPファイルの名前には最初のファイルの名前を拡張子zipにしてつかう zip_path = os.path.join(temp_dir, os.path.splitext(received_files[0].name)[0] + '.zip') for f in received_files: # pyminizipに渡す時に一時ファイルのままだと、名前がランダムな感じで良くないので # request.FILESから取り出すして使う temp_path = os.path.join(temp_dir, f.name) with open(temp_path, "wb") as tmp_f: tmp_f.write(f.read()) temp_file_list.append(temp_path) pyminizip.compress_multiple(temp_file_list, zip_path, password, 2) temp_zip = File(open(zip_path, "rb")) # djangoのmodel zipfile = ZipFile() # zip_pathのままにしてしまうと、/tmp/xxxの階層つきでZIPに入ってしまうのでファイル名だけ渡す zipfile.file_field.save(os.path.basename(zip_path), temp_zip) zipfile.save()
Django1.10 QUICKSTART-BOOK with Python3: 作りながら学ぶDjangoアプリケーション開発
- 作者: 淵上 喜弘
- 出版社/メーカー: 淵上 喜弘
- 発売日: 2016/12/04
- メディア: Kindle版
- この商品を含むブログを見る
Django×Python (LLフレームワークBOOKS)
- 作者: 露木誠
- 出版社/メーカー: 技術評論社
- 発売日: 2009/02/16
- メディア: 単行本(ソフトカバー)
- 購入: 10人 クリック: 129回
- この商品を含むブログ (36件) を見る
- 作者: 淵上 喜弘
- 発売日: 2017/05/10
- メディア: Kindle版
- この商品を含むブログを見る