ファイルのアップロード
Djangoがファイルのアップロードを処理すると、ファイルデータは request.FILES に配置されます(request
オブジェクトの詳細については、要求および応答オブジェクトのドキュメントを参照してください)。 。 このドキュメントでは、ファイルがディスクとメモリに保存される方法と、デフォルトの動作をカスタマイズする方法について説明します。
警告
信頼できないユーザーからアップロードされたコンテンツを受け入れる場合、セキュリティ上のリスクがあります。 緩和策の詳細については、ユーザーがアップロードしたコンテンツに関するセキュリティガイドのトピックを参照してください。
基本的なファイルのアップロード
FileField を含む単純なフォームについて考えてみます。
forms.py
このフォームを処理するビューは、 request.FILES でファイルデータを受け取ります。これは、各 FileField (または ImageField 、またはその他ののキーを含むディクショナリです。フォーム内のX181X] FileField サブクラス)。 したがって、上記のフォームのデータにはrequest.FILES['file']
としてアクセスできます。
request.FILES には、リクエストメソッドがPOST
であり、リクエストを投稿した<form>
の属性がenctype="multipart/form-data"
である場合にのみデータが含まれることに注意してください。 それ以外の場合、request.FILES
は空になります。
ほとんどの場合、アップロードされたファイルをフォームにバインドするで説明されているように、ファイルデータをrequest
からフォームに渡すだけです。 これは次のようになります。
views.py
request.FILES をフォームのコンストラクターに渡す必要があることに注意してください。 これは、ファイルデータがフォームにバインドされる方法です。
アップロードされたファイルを処理する一般的な方法は次のとおりです。
read()
を使用する代わりにUploadedFile.chunks()
をループすることで、大きなファイルがシステムのメモリを圧倒しないようにします。
UploadedFile
オブジェクトで使用できる他のメソッドと属性がいくつかあります。 完全なリファレンスについては、 UploadedFile を参照してください。
モデルを使用したアップロードファイルの処理
Model に FileField を使用してファイルを保存する場合、 ModelForm を使用するとこのプロセスがはるかに簡単になります。 ファイルオブジェクトは、form.save()
を呼び出すときに、対応する FileField の upload_to 引数で指定された場所に保存されます。
オブジェクトを手動で作成している場合は、ファイルオブジェクトを request.FILES からモデルのファイルフィールドに割り当てるだけです。
複数のファイルをアップロードする
1つのフォームフィールドを使用して複数のファイルをアップロードする場合は、フィールドのウィジェットのmultiple
HTML属性を設定します。
forms.py
次に、 FormView サブクラスのpost
メソッドをオーバーライドして、複数のファイルのアップロードを処理します。
views.py
ハンドラーのアップロード
ユーザーがファイルをアップロードすると、Djangoはファイルデータをアップロードハンドラーに渡します。これは、アップロード時にファイルデータを処理する小さなクラスです。 アップロードハンドラーは、最初は:setting: `FILE_UPLOAD_HANDLERS` 設定で定義されます。デフォルトは次のとおりです。
MemoryFileUploadHandler と TemporaryFileUploadHandler を組み合わせることで、小さなファイルをメモリに、大きなファイルをディスクに読み込むというDjangoのデフォルトのファイルアップロード動作が提供されます。
Djangoがファイルを処理する方法をカスタマイズするカスタムハンドラーを作成できます。 たとえば、カスタムハンドラーを使用して、ユーザーレベルの割り当てを適用したり、データをその場で圧縮したり、プログレスバーをレンダリングしたり、データをローカルに保存せずに別の保存場所に直接送信したりすることもできます。 アップロード動作をカスタマイズまたは完全に置き換える方法の詳細については、カスタムアップロードハンドラーの作成を参照してください。
アップロードされたデータが保存される場所
アップロードしたファイルを保存する前に、データをどこかに保存する必要があります。
デフォルトでは、アップロードされたファイルが2.5メガバイトよりも小さい場合、Djangoはアップロードの内容全体をメモリに保持します。 これは、ファイルの保存にはメモリからの読み取りとディスクへの書き込みのみが含まれるため、非常に高速であることを意味します。
ただし、アップロードされたファイルが大きすぎる場合、Djangoはアップロードされたファイルをシステムの一時ディレクトリに保存されている一時ファイルに書き込みます。 Unixライクなプラットフォームでは、これはDjangoが/tmp/tmpzfp6I6.upload
のようなファイルを生成することを期待できることを意味します。 アップロードが十分に大きい場合は、Djangoがデータをディスクにストリーミングするときにこのファイルのサイズが大きくなるのを見ることができます。
これらの詳細–2.5メガバイト。 /tmp
; NS。 –は単に「合理的なデフォルト」であり、次のセクションで説明するようにカスタマイズできます。
オンザフライでのアップロードハンドラーの変更
特定のビューで異なるアップロード動作が必要になる場合があります。 このような場合、request.upload_handlers
を変更することで、リクエストごとにアップロードハンドラーをオーバーライドできます。 デフォルトでは、このリストには:setting: `FILE_UPLOAD_HANDLERS` で指定されたアップロードハンドラーが含まれますが、他のリストと同じようにリストを変更できます。
たとえば、ある種のAJAXウィジェットへのアップロードの進行状況に関するフィードバックを提供するProgressBarUploadHandler
を作成したとします。 このハンドラーをアップロードハンドラーに次のように追加します。
プログレスバーハンドラーは他のハンドラーの前にを実行する必要があるため、この場合は(append()
の代わりに)list.insert()
を使用することをお勧めします。 アップロードハンドラーは順番に処理されることを忘れないでください。
アップロードハンドラーを完全に置き換える場合は、新しいリストを割り当てるだけです。
ノート
request.POST
またはrequest.FILES
にアクセスするの前にアップロードハンドラーを変更することしかできません。アップロード処理がすでに開始された後でアップロードハンドラーを変更することは意味がありません。 request.POST
またはrequest.FILES
から読み取った後にrequest.upload_handlers
を変更しようとすると、Djangoはエラーをスローします。
したがって、常にビューのできるだけ早い段階でアップロードハンドラーを変更する必要があります。
また、request.POST
は、デフォルトで有効になっている CsrfViewMiddleware によってアクセスされます。 つまり、アップロードハンドラーを変更できるようにするには、ビューで csrf_exempt()を使用する必要があります。 次に、実際にリクエストを処理する関数で csrf_protect()を使用する必要があります。 これは、CSRFチェックが行われる前にハンドラーがファイルアップロードの受信を開始する可能性があることを意味することに注意してください。 コード例: