【Django】モデルを使用せずに画像・PDFファイルをサーバーにアップロードする

2020.08.27 /

【Django】モデルを使用せずに画像・PDFファイルをサーバーにアップロードする

Djangoで作成したサイト内で、画像やPDFなどのファイルをサーバー内のディレクトリにアップロードしたいことがあるかと思います。

モデルを作成して、そのモデルを通してMEDIAフォルダ内にファイルを保存するのが多いですが、モデルをわざわざ通さない(データベースに登録しない)で、ただ単にファイルをサーバーにアップロードする方法を今回はご紹介します。

使い道としては、私の場合ですが、サイトを通してアップロードされた画像ファイルを解析して、その解析結果を表示するWebアプリケーション等で使用しております。

モデルを利用(フィールドImageFieldの利用)して画像ファイルのアップロードおよび表示(配信)を行う場合は、以下記事で紹介している方法を活用してください。

当記事は、すでにDjangoによってサイト(Webアプリケーション)が作成できている方を対象としています。
DjangoでのWebサイト・アプリを作成する方法がわからない方は、以下記事をご参考にしてください。

アップロード機能を追加するポイント

以下にアップロード機能を追加するための、各追加項目を記載しています。
以下各pyファイルへの追加の流れは、この順番で行わなくても問題ないです。

最終的に紹介しているpyファイルへの変更がすべてできていれば正常に動作します。

変更ポイント

forms.pyにアップロード用のクラスを作成する

必要であればurls.pyを変更する

views.pyにPOST送信時の動作を追記する

テンプレートにアップロードformを追加する

今回はモデル・データベースは一切使用しないので、models.pyは触りません。
アップロードに使用するフォームのためのforms.py、テンプレートのhtmlファイル、urls.py、views.pyの4つのファイルを触ります。

作成するファイルアップロードページは以下のようになります。

Djangoアップロード機能を付けたサイト画面

forms.pyにアップロード用のクラスを作成する

まずforms.pyにファイルをアップロードするためのフォームクラスを作成します。

from django import forms

class UploadImageForm(forms.Form):
    Uploadfile = forms.FileField()

UploadfileにはFileFieldを指定しています。

必要であればurls.pyを変更する

作成したアプリケーション内のurls.pyは以下のようにしています。

from django.urls import path
from . import views
urlpatterns = [
    path('', views.index, name='index'),
]

ここではurls.pyの書き方などについては言及しません。
pathは適宜変更していただければと思います。

views.pyにPOST送信時の動作を追記する

views.pyは以下のように記述します。

from django.shortcuts import render
from .forms import UploadImageForm
from django.conf import settings

def index(request):
    if request.method == "POST":    #1
        form = UploadImageForm(request.POST, request.FILES)
        updata = request.FILES['Uploadfile']    #2
        with open(settings.BASE_DIR + '/media/upload/test.pdf', 'wb+') as f:    #3
            for chunk in updata.chunks():
                f.write(chunk)
    form = UploadImageForm()
    context = {'form': form,}
    return render(request, 'index.html', context)

#1では、フォームからPOST送信(画像の送信)があるかどうかを判定しています。
POST送信がある場合は、#1以下を実行します。

#2では、フォームから送信されたファイルデータをupdata変数に入れています。
フォームから送信されるファイルデータは、request.FILESに格納されます。

ここで注意すべき点は、
request.FILES にデータが格納されるのは、フォームからのリクエストが POST 送信であり、かつ

属性にenctype="multipart/form-data" が設定されている場合のみです。

それ以外では、request.FILES は空になります。

#3では、settings.BASE_DIRを使用しています。これはmanage.pyがある階層を示しています。
詳しくは以下リンクをご覧ください。

またここで保存先として指定している、media/uploadのフォルダは事前に作成する必要があります。

テンプレートにアップロード用formを追加する

最後にテンプレートにアップロード用のフォームを記述します。

<html>
<body style="margin:20px;">
  <h1>ファイルアップロードページ</h1>
  <form class="" method="POST" enctype="multipart/form-data">
    
    
    <p><input type="submit" name="btn_upload" value="UPLOAD"></p>
  </form>
</body>
</html>

ここで注意する点としては、formにenctype="multipart/form-data"の指定をする必要があるということです。

まとめ

Djangoにおけるモデル・データベースを介さない、ファイルをサーバーにアップロードする方法はいかがでしたか?

modelを使ってのファイルアップロードと比べて、そこまで使い道は多くないですが、覚えておいて損はないと思います。

ぜひ使ってみてください。