2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Django 汎用クラスビューでファイルをアップロードする方法

Posted at

2020-04-07 作成: windows10/Python-3.8.2-amd64/Django-3.0.4

Django でファイルを汎用クラスビューでアップロードする方法について、
日本語情報は意外と多くありません。
そのため、結構時間がかかってしまいました。
忘れないように記事にしておきます。
この記事は、ファイルのアップロードの原理を手軽に知りたい、という人向きです。

Django を初めて使う人は、こちら。
10 分で終わる Django の実用チュートリアル

前準備

プロジェクト名は mysite、アプリケーション名は fileupload とする。
フォルダ media を mysite/ に作成し、ファイルの保存場所とする。

ここまでのファイルの配置はこうなる。

mysite/
    mysite/
        __pycashe__/    <- 気にしなくていい
        setting.py, urls.py など *.py が 5 個
    fileupload/
        migrations/     <- 気にしなくていい
        models.py, views.py など *.py が 6 個
    media/              <- アップロードしたファイルの保存場所
    manage.py           <- プロジェクトの管理用

Django プロジェクトに、アプリケーション fileupload を登録する。
そのために、settings.py の INSTALLED_APPS に追記。

mysite/mysite/settings.py
INSTALLED_APPS = [
    'fileupload.apps.FileuploadConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

ファイルのアップロード用のディレクトリも登録する。
そのために、settings.py に 2 行を追記。

mysite/mysite/settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

url を登録するため urls.py に追記。

mysite/mysite/urls.py
from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('fileupload/', include('fileupload.urls')),
    path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

アプリケーションの実装

モデル Fileupload を作成。
フィールドは、ファイルのタイトルと、ファイルそのものの 2 つ。
ファイルの保存場所は、media/uploads/年/月/日 という名前のフォルダ。
写真をアップロードすることを想定し、拡張子は jpg しか相手にしない。

mysite/fileupload/models.py
from django.db import models
from django.core.validators import FileExtensionValidator

class Fileupload(models.Model):
    titlefield = models.CharField(max_length = 200, null = True)
    filefield = models.FileField(
        upload_to = 'uploads/%Y/%m/%d/',
        verbose_name = 'attached file',
        validators=[FileExtensionValidator(['jpg', ])],
        null = True
    )

ビューを作成する。
Django の汎用クラスビューを使うのは、やっぱり楽だから。
汎用クラスビューは、デフォルトの変数名やファイル名など
(たとえばfileupload_object_nametemplate_name )を知っていないと使えない。
だから、デフォルト名ではなく、分かりやすい名前を明示的につけておいた。

mysite/fileupload/views.py
from django.views import generic
from .models import Fileupload

class FileuploadListView(generic.ListView):
    model = Fileupload
    context_object_name = 'fileupload_context_list'

class FileuploadCreateView(generic.CreateView):
    model = Fileupload
    fields = ['titlefield', 'filefield']
    success_url = '/fileupload'
    template_name = 'fileupload/fileupload_create.html'

class FileuploadDetailView(generic.DetailView):
    model = Fileupload
    template_name = 'fileupload/fileupload_detail.html'
    context_object_name = 'fileupload_context'

class FileuploadUpdateView(generic.UpdateView):
    model = Fileupload
    fields = ['titlefield', 'filefield']
    success_url = '/fileupload'
    template_name = 'fileupload/fileupload_update.html'

class FileuploadDeleteView(generic.DeleteView):
    model = Fileupload
    success_url = '/fileupload'
    template_name = 'fileupload/fileupload_delete.html'

ビューを url に登録する。
ファイル fileupload/urls.py を新しく作成。
作成したビューを登録する。

mysite/fileupload/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.FileuploadListView.as_view()),
    path('index', views.FileuploadListView.as_view(),
        name = 'site_index'),
    path('create', views.FileuploadCreateView.as_view(),
        name = 'site_create'),
    path('detail/<int:pk>', views.FileuploadDetailView.as_view(),
        name = 'site_detail'),
    path('update/<int:pk>', views.FileuploadUpdateView.as_view(),
        name = 'site_update'),
    path('delete/<int:pk>', views.FileuploadDeleteView.as_view(),
        name = 'site_delete'),
]

fileupload/templates/fileupload/にテンプレート用の html ファイルを作成する。
それぞれのビューに対応する。

mysite/fileupload/templates/fileupload/fileupload_list.html
<h1>ファイルの一覧表示</h1>

{% if fileupload_context_list %}
  <table>
  {% for temp in fileupload_context_list %}
    <tr>
      <td><a href = "{% url 'site_detail' temp.pk %}"> {{ temp.titlefield }}</a></td>
      <td>{{ temp.filefield }}</td>
      <td><a href = "{% url 'site_update' temp.pk %}">Edit</a></td>
      <td><a href = "{% url 'site_delete' temp.pk %}">Delete</a></td>
    </tr>
  {% endfor %}
  </table>

{% else %}
<p>No file available.</p>

{% endif %}
<p><a href = "{% url 'site_create' %}">新しいファイルのアップロード</a></p>
mysite/fileupload/templates/fileupload/fileupload_create.html
<h1>ファイルのアップロード</h1>

<form method = "post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.titlefield }}
    {{ form.filefield }}
    <input type = "submit" value = "Create" />
</form>
mysite/fileupload/templates/fileupload/fileupload_detail.html
<h1>ファイルの詳細</h1>

{% if fileupload_context %}
  <ul>
    <li>Primary Key Number : {{ fileupload_context.pk }}</li>
    <li>Memo Text : {{ fileupload_context.titlefield }}</li>
    <li>Memo Text : /media/{{ fileupload_context.filefield }}</li>
    <li>File : <img src = /media/{{ fileupload_context.filefield }} /></li>
  </ul>

{% else %}
<p>No file available.</p>

{% endif %}
<p><a href = "{% url 'site_index' %}">ファイルの一覧表示</a></p>
mysite/fileupload/templates/fileupload/fileupload_update.html
<h1>ファイルの更新</h1>

<form method = "post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.titlefield }}
    {{ form.filefield }}
    <input type = "submit" value = "Save" />
</form>
mysite/fileupload/templates/fileupload/fileupload_delete.html
<h1>ファイルの削除</h1>

<form method = "post">
    {% csrf_token %}
    <input type= "submit" value = "Delete" />
</form>

仕上げ

マイグレーションを実行し、開発用 www サーバーを起動すれば、
http://localhost:8000/fileupload/ でアクセスできる。

課題

ファイルのアップロードに失敗したときの処理は、ちゃんと書いていないので今後の課題。

おしまい

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?