https://intellectual-curiosity.tokyo/2018/12/18/django%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/


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

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

条件

  • Django 2.1.4
  • Python 3.7.0

アップロード処理の実装

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

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

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

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

  1. projectName
  2. ├projectName
  3. └monitor
  4. ├migrations
  5. ├templates
  6. └uploads ←ここにアップロードしたファイルが保存される
  7. ・・
  8. ・・

urls.py

  1. # urls.py抜粋
  2. from django.urls import path
  3. from . import views
  4. app_name = 'monitor'
  5. urlpatterns = [
  6. ・・・
  7. # ファイルアップロード用
  8. path('monitor/upload/', views.upload, name='upload'),
  9. path('monitor/upload_complete/', views.upload_complete, name='upload_complete'),
  10. ]

views.py

  1. # views.py抜粋
  2. import os
  3. from .forms import UploadFileForm
  4. UPLOAD_DIR = os.path.dirname(os.path.abspath(__file__)) + '/uploads/' # アップロードしたファイルを保存するディレクトリ
  5. # アップロードされたファイルのハンドル
  6. def handle_uploaded_file(f):
  7. path = os.path.join(UPLOAD_DIR, f.name)
  8. with open(path, 'wb+') as destination:
  9. for chunk in f.chunks():
  10. destination.write(chunk)
  11. # ファイルアップロード
  12. def upload(request):
  13. if request.method == 'POST':
  14. form = UploadFileForm(request.POST, request.FILES)
  15. if form.is_valid():
  16. handle_uploaded_file(request.FILES['file'])
  17. return redirect('monitor:upload_complete') # アップロード完了画面にリダイレクト
  18. else:
  19. form = UploadFileForm()
  20. return render(request, 'monitor/upload.html', {'form': form})
  21. # ファイルアップロード完了
  22. def upload_complete(request):
  23. return render(request, 'monitor/upload_complete.html')

forms.py

  1. # forms.py
  2. from django import forms
  3. class UploadFileForm(forms.Form):
  4. file = forms.FileField()

テンプレート

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

  1. <!-- upload.html -->
  2. {% extends 'base.html' %}
  3. {% block content %}
  4. <h1>アップロード サンプル</h1>
  5. <form method="POST" enctype="multipart/form-data">
  6. {% csrf_token %}
  7. {{ form }}
  8. <div class="form-group">
  9. <button type="submit">アップロード</button>
  10. </div>
  11. </form>
  12. {% endblock %}
  1. <!-- upload_complete.html -->
  2. {% extends 'base.html' %}
  3. {% block content %}
  4. <h1>アップロード完了</h1>
  5. <a href="{% url 'monitor:upload' %}"><button>戻る</button></a>
  6. {% endblock %}

実行結果

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

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

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

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

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

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

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

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

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

forms.py

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

  1. # forms.py
  2. from django import forms
  3. import os
  4. VALID_EXTENSIONS = ['.csv']
  5. class UploadFileForm(forms.Form):
  6. file = forms.FileField(
  7. label='アップロードファイル',
  8. )
  9. def clean_file(self):
  10. file = self.cleaned_data['file']
  11. extension = os.path.splitext(file.name)[1] # 拡張子を取得
  12. if not extension.lower() in VALID_EXTENSIONS:
  13. raise forms.ValidationError('csvファイルを選択してください!')

実行結果

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

参考

サンプルソース

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

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

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


+ Recent posts