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 に追記。
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 行を追記。
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
url を登録するため 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 しか相手にしない。
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_name
や template_name
)を知っていないと使えない。
だから、デフォルト名ではなく、分かりやすい名前を明示的につけておいた。
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 を新しく作成。
作成したビューを登録する。
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 ファイルを作成する。
それぞれのビューに対応する。
<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>
<h1>ファイルのアップロード</h1>
<form method = "post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.titlefield }}
{{ form.filefield }}
<input type = "submit" value = "Create" />
</form>
<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>
<h1>ファイルの更新</h1>
<form method = "post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.titlefield }}
{{ form.filefield }}
<input type = "submit" value = "Save" />
</form>
<h1>ファイルの削除</h1>
<form method = "post">
{% csrf_token %}
<input type= "submit" value = "Delete" />
</form>
仕上げ
マイグレーションを実行し、開発用 www サーバーを起動すれば、
http://localhost:8000/fileupload/ でアクセスできる。
課題
ファイルのアップロードに失敗したときの処理は、ちゃんと書いていないので今後の課題。
おしまい