Djangoでファイルをアップロードする方法

Djangoでファイルをアップロードする方法をご紹介します。

条件

  • Django 2.1.4
  • Python 3.7.0

アップロード処理の実装

「アップロード画面」と「アップロード完了画面」を作成します。

  • アップロード画面:ファイルを選択してアップロード実行
  • アップロード完了画面:アップロードが完了したら表示

アップロード先ディレクトリ作成

アップロードしたファイルの保存先として以下のディレクトリ(uploads)を作成します。

projectName
├projectName
└monitor
  ├migrations
  ├templates
  └uploads ←ここにアップロードしたファイルが保存される
・・
・・

urls.py

# urls.py抜粋

from django.urls import path
from . import views

app_name = 'monitor'

urlpatterns = [

    ・・・

    # ファイルアップロード用
    path('monitor/upload/', views.upload, name='upload'),
    path('monitor/upload_complete/', views.upload_complete, name='upload_complete'),
]

views.py

# views.py抜粋

import os
from .forms import UploadFileForm

UPLOAD_DIR = os.path.dirname(os.path.abspath(__file__)) + '/uploads/'  # アップロードしたファイルを保存するディレクトリ


# アップロードされたファイルのハンドル
def handle_uploaded_file(f):
    path = os.path.join(UPLOAD_DIR, f.name)
    with open(path, 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)


# ファイルアップロード
def upload(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            return redirect('monitor:upload_complete')  # アップロード完了画面にリダイレクト
    else:
        form = UploadFileForm()
    return render(request, 'monitor/upload.html', {'form': form})


# ファイルアップロード完了
def upload_complete(request):
    return render(request, 'monitor/upload_complete.html')

forms.py

# forms.py

from django import forms


class UploadFileForm(forms.Form):
    file = forms.FileField()

テンプレート

アップロード画面:upload.html、アップロード完了画面:upload_complete.htmlを作成します。
(monitor/templates/monitorの下に作成)

<!-- upload.html -->
{% extends 'base.html' %}

{% block content %}

<h1>アップロード サンプル</h1>

<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form }}
    <div class="form-group">
        <button type="submit">アップロード</button>
    </div>
</form>

{% endblock %}
<!-- upload_complete.html -->

{% extends 'base.html' %}

{% block content %}

<h1>アップロード完了</h1>

<a href="{% url 'monitor:upload' %}"><button>戻る</button></a>

{% endblock %}

実行結果

Djangoを起動して以下のURLにアクセスします。

http://127.0.0.1:8000/monitor/upload/

ファイル選択とアップロードボタンが表示されます。

ファイルを選択せずにアップロードボタンを押すと、警告メッセージが表示されます。

ファイルを選択すると、選択したファイル名が表示されます。

アップロードを実行すると、アップロード完了画面に遷移します。

指定のディレクトリに対象ファイルがアップロードされました。

ファイル種別のバリデーション

アップロードするファイル種別を限定する処理を実装します。
ここではcsvファイルのみを許可するようにします。

forms.py

フォームにバリデーションチェックのメソッドを追加します。
(csv以外の拡張子も受け入れたい場合、対象の拡張子をVALID_EXTENSIONSに追加します。)

# forms.py

from django import forms
import os

VALID_EXTENSIONS = ['.csv']


class UploadFileForm(forms.Form):
    file = forms.FileField(
        label='アップロードファイル',
    )

    def clean_file(self):
        file = self.cleaned_data['file']
        extension = os.path.splitext(file.name)[1] # 拡張子を取得
        if not extension.lower() in VALID_EXTENSIONS:
            raise forms.ValidationError('csvファイルを選択してください!')

実行結果

csv以外のファイルをアップロードしようとするとエラーメッセージが表示されます。

参考

サンプルソース

サンプルソースをGitHubに公開しています。
https://github.com/kzmrt/graph

Django公式:ファイルのアップロード

https://docs.djangoproject.com/ja/2.1/topics/http/file-uploads/

Djangoでファイルをアップロードする方法” に対して2件のコメントがあります。

コメントを残す

メールアドレスが公開されることはありません。