4
5

More than 3 years have passed since last update.

【Django】modelを使わない画像ファイルアップロード機能を実装する

Posted at

はじめに

Djangoアプリで画像ファイルをアップロードする場合ImageFieldを使用してDBに保存するのが定石だと思います。
しかし、先日実務で作ったアプリは他システムとの統合の都合上DBではなく特定のフォルダにファイルを保存する必要があり、その方法を調べるのに少し時間がかかったので記事にしておきます。

結論

forms.ImageFieldを使用して実現可能です。

サンプル

以下、最小構成のサンプルです。

トップページ
image.png

適当な画像ファイルを選択して送信すると画面が変わります。
image.png

プロジェクトのベースディレクトリを見ると「media_root」フォルダが作成されており、中にアップロードしたファイルが保存されています。
image.png

画像以外のファイルをアップロードした場合エラーメッセージが表示されます。
image.png

ソース

forms.py
import datetime
from django import forms
from django.core.files.storage import default_storage


class FileUploadSampleForm(forms.Form):
    file = forms.ImageField()

    def save(self):
        """ファイルを保存するメソッド"""
        now_date = datetime.datetime.now().strftime('%Y%m%d%H%M%S')  # ファイル名に現在時刻を付与するため取得
        upload_file = self.files['file']  # フォームからアップロードファイルを取得
        file_name = default_storage.save(now_date + "_" + upload_file.name, upload_file)  # ファイルを保存 戻り値は実際に保存したファイル名
        return default_storage.url(file_name)
views.py
from django.shortcuts import render
from django.views.generic import View
from .forms import FileUploadSampleForm


class IndexView(View):
    def get(self, request, *args, **kwargs):
        """GETリクエスト用のメソッド"""
        form = FileUploadSampleForm
        return render(request, 'fileUploadSample/index.html', {"form": form})

    def post(self, request, *args, **kwargs):
        """POSTリクエスト用のメソッド"""
        form = FileUploadSampleForm(request.POST, request.FILES)

        if not form.is_valid():
            return render(request, 'fileUploadSample/index.html', {"form": form})

        filename_save = form.save()

        context = {
            'form': form,
            'filename_save': filename_save,
        }
        return render(request, 'fileUploadSample/index.html', context)


index = IndexView.as_view()

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="{% url 'fileUploadSample:index' %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}

    {#forms.ImageFieldを表示#}
    {{ form.file }}
    <br><br>

    {#エラーメッセージを表示#}
    {% for field in form %}
        {% if form.errors %}
            <font color=#CC3300>{{ field.errors }}</font><br>
        {% endif %}
    {% endfor %}

    {#保存されたファイル名を表示#}
    {% if filename_save %}
        ファイル名 {{ filename_save }} で保存されました。
        <br><br>
    {% endif %}

    <input type="submit" value="送信"/>
</form>
</body>
</html>
urls.py
from django.urls import path
from . import views

app_name = 'fileUploadSample'
urlpatterns = [
    path('', views.index, name='index'),
]

settings.pyには以下を追記しておいてください。

settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media_root')

  
 
forms.FileFieldを使用することで画像以外のファイルのアップロードに対応することもできます(画像ファイルで無い場合もform.is_valid()でエラーが出なくなる)。

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

4
5
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
4
5