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

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

条件

  • Django 2.1.4
  • Python 3.7.0

アップロード処理の実装

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

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

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

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
projectName
├projectName
└monitor
├migrations
├templates
└uploads ←ここにアップロードしたファイルが保存される
・・
・・
projectName ├projectName └monitor ├migrations ├templates └uploads ←ここにアップロードしたファイルが保存される ・・ ・・
projectName
├projectName
└monitor
  ├migrations
  ├templates
  └uploads ←ここにアップロードしたファイルが保存される
・・
・・

urls.py

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 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'),
]
# 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'), ]
# 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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 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')
# 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')
# 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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# forms.py
from django import forms
class UploadFileForm(forms.Form):
file = forms.FileField()
# forms.py from django import forms class UploadFileForm(forms.Form): file = forms.FileField()
# forms.py

from django import forms


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

テンプレート

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!-- 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.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.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 %}
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!-- upload_complete.html -->
{% extends 'base.html' %}
{% block content %}
<h1>アップロード完了</h1>
<a href="{% url 'monitor:upload' %}"><button>戻る</button></a>
{% endblock %}
<!-- upload_complete.html --> {% extends 'base.html' %} {% block content %} <h1>アップロード完了</h1> <a href="{% url 'monitor:upload' %}"><button>戻る</button></a> {% 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に追加します。)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 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ファイルを選択してください!')
# 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ファイルを選択してください!')
# 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件のコメントがあります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です