【Django】ファイルアップロード機能を実装する

 

こんにちは。のっくんです。

 

今日の記事では、Djangoのファイルアップロード機能を実装する方法を紹介します。

 

「Djangoでファイルアップロードページを作りたい」

 

そんな方に読んでいただければと思います。

 

[toc]

 

完成形

 

作成するページの見た目は以下のようなシンプルなものです。

 

 

Descriptionにアップロードするファイル名、Documentにアップするファイルを指定します。

 

Uploadボタンを押すと、アップロードされます。

 

アプリケーションの作成

 

以下のコマンドでmosaic_appと言う名前のプロジェクトを作成して、その中にhelloと言う名前のアプリケーションを作成します。

 

django-admin startproject mosaic_app
cd mosaic_app/
python manage.py startapp hello

 

このhelloアプリケーションにファイルのアップロード機能を実装します。

 

├── mosaic_app
│   ├── db.sqlite3
│   ├── hello
│   ├── manage.py
│   ├── media
│   ├── mosaic_app
│   └── static

 

画像のアップロード先はmedia/documentsディレクトリにしたいと思います。

 

プロジェクト全体の設定とURL

 

画像をアップロードするディレクトリを指定します。

 

settings.pyの下の方に以下を追加しましょう。

 

mosaic_app/settings.py

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

 

また、タイムゾーンを日本にしておきます。

 

TIME_ZONE = 'Asia/Tokyo'

 

URLの設定は以下のようにしておきます。

 

mosaic_app/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', include('hello.urls'))
]

 

hello/urls.py

urlpatterns = [
    path('upload', views.model_form_upload, name='upload')
]

 

モデルの作成

 

では早速モデルを作っていきましょう。helloアプリの中にあるmodels.pyを以下のようにします。

 

hello/models.py

from django.db import models

class Document(models.Model):
    description = models.CharField(max_length=255,blank=True)
    document = models.FileField(upload_to='documents/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

 

documentがFileFiledで定義されています。ここでファイルのアップロード先を(documents/)にしています。この設定によってmedia/documentsに画像がアップロードされるようになります。

 

DateTimeFieldを定義して投稿日時が分かるようにしています。auto_now_addを指定することで自動的に投稿日時がデータベースに書き込まれるようになります。

 

フォームの作成

 

このファイルは存在しないので自分で新しく作成します。

 

hello/forms.py

from django import forms
from .models import Document

class DocumentForm(forms.ModelForm):
    class Meta:
        model = Document
        fields = ('description', 'document', )

 

fieldsのなかに投稿日時はありませんが、システムで自動的に追加されるようにしてあるのでユーザが指定する必要はありません。

 

ビューの編集

 

ビューでは以下の関数を作ります。

 

hello/views.py

from django.shortcuts import render,redirect
from .forms import DocumentForm
from .models import Document

def model_form_upload(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('index')
    else:
        form = DocumentForm()
    return render(request, 'hello/model_form_upload.html', {
        'form': form
    })

 

model_form_uploadでは、投稿されたファイルの保存やフォームの受け渡しを行なっています。投稿ページはmodel_form_upload.htmlにしています。

 

テンプレートの作成

 

以下のようにテンプレートを作成します。

 

hello/templates/hello/model_form_upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Upload</title>
</head>
<body>

    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Upload</button>
    </form>

</body>
</html>

 

enctypeを指定しないと上手くアップロードできないそうなので気をつけてください。

 

以上のコードを記載したら、以下のコマンドを実行してください。

 

python manage.py makemigrations hello
python manage.py migrate
python manage.py runserver

 

ブラウザで”localhost:8000/hello/upload”にアクセスするとページが表示されます。

 

アップされたファイルを確認する方法

 

*2019/1/7 追記

 

これは必須ではありませんが、以下のようにするとアップされたファイル名や日時を確認できます。

 

hello/views.py

from django.shortcuts import render,redirect
from .forms import DocumentForm
from .models import Document

def model_form_upload(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('index')
    else:
        form = DocumentForm()
        obj = Document.objects.all()
    return render(request, 'hello/model_form_upload.html', {
        'form': form,
        'obj': obj
    })

 

hello/templates/hello/model_form_upload.html

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Upload</title>
    </head>
    <body>

        <form method="post" enctype="multipart/form-data">
            {% csrf_token %}
            {{ form.as_p }}
            <button type="submit">Upload</button>
        </form>

     {% for item in obj %}
    <tr>
        <td>{{ item.description }}</td>
        <td>{{ item.document }}</td>
        <td>{{ item.uploaded_at }}</td>
    <tr>
    {% endfor %}
    </body>
</html>

 

参考URL

How to Upload Files With Django:

https://simpleisbetterthancomplex.com/tutorial/2016/08/01/how-to-upload-files-with-django.html

 

以上です。お疲れ様でした。

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog