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/