【Django】アップロードされた画像を削除する

このページでは、Django でのアップロードされた画像の削除の仕方について解説していきます。

下記ページで画像のアップロードについて解説していますが、今回は逆にアップロードされた画像のファイルを削除する手順を解説していきます。

Djangoでの画像のアップロードの実現方法解説ページアイキャッチ【Django】画像をアップロードする

といっても、画像のアップロードさえ実現できていれば、アップロードされた画像のファイルの削除も簡単に実現できます。

ただ、ちょっと注意点があるので、その辺りを中心に解説させていただきたいと思います。

申し訳ありませんが、ImageField を用いた画像のアップロード手順をご存知であることを前提に解説させていただきますので、画像のアップロード手順をご存知ない方は、まずは上記ページでその手順について理解しておいていただければと思います。

アップロードされた画像の削除

では、アップロードされた画像の削除の仕方について解説していきます。

アップロードされた画像の削除における注意点

下記ページの 画像アップロード用の Model の作成 でも解説していますが、ImageField を持つ Model のインスタンスに save メソッドを実行させた場合、レコードの保存だけでなくアップロードされた画像のファイル保存も行われます。

Djangoでの画像のアップロードの実現方法解説ページアイキャッチ【Django】画像をアップロードする

それに対し、ImageField を持つ Model のインスタンスに delete メソッドを実行させた場合、削除されるのは save メソッド実行時に保存された “レコードのみ” です。

つまり、ImageField を持つ Model のインスタンスに delete メソッドを実行させても、保存された画像ファイルは削除されません

なので、保存された画像ファイルの削除に関しては、レコードの削除とは別に行う必要があります。

その保存された画像ファイルの削除は、ImageField のインスタンスに delete メソッドを実行させることで行うことができます。

MEMO

実際には、delete メソッドを実行するのは ImageFieldFile のインスタンスとなります

が、今回は簡単のため、ImageField のインスタンスが delete メソッドを実行する前提で解説をさせていただきます

スポンサーリンク

アップロードされた画像を削除する手順

ですので、アップロードされた画像を削除する際には下記のような手順を踏むことになります。

  • 削除したい画像に対応する Model のインスタンスを取得する
  • Model のインスタンスの ImageField のデータ属性に delete メソッドを実行させる

アップロードされた画像だけでなく、その画像に対応するレコードもデータベースから削除したい場合は下記の手順も必要になります。

  • Model のインスタンスに delete メソッドを実行させる

例えば、ImageField 持つ Model を下記の UploadImage とした時、

Modelの例

from django.db import models

class UploadImage(models.Model):
    image = models.ImageField(upload_to='img/')

下記のような関数を View などから実行させるようにすれば、引数 image_id で指定した id を持つレコード、および、そのレコード保存時に一緒に保存された画像ファイルを削除することが可能です。

画像ファイルとレコードの削除

def delete(image_id=0):

    # UploadImageのインスタンスを取得
    upload_image = get_object_or_404(UploadImage, id=image_id)
    
    # 画像ファイルの削除
    upload_image.image.delete()
    
    # レコードの削除
    upload_image.delete()

上記において、upload_image.image.delete() により、画像ファイルの削除が行われます。

さらに、upload_image.delete() により、レコードの削除が行われます。

このように画像ファイルの削除とレコードの削除を行う場合、先に画像ファイルの削除を行う必要がある点に注意してください。

upload_image.image.delete() 等により画像ファイルの削除を行った際には、保存されているレコードの画像のファイルパスのフィールドが空白にされ、その状態でレコードが保存されることになります。

その時、すでにレコードの削除を行なった状態であると、そのレコード保存で新たなレコードが保存されてしまうことになります(画像のファイルパスのフィールドが空白であるレコード)。

そうなると、不要なレコードがデータベースに残ってしまうことになります。これを防ぐため、上記の手順で削除を行う場合、画像ファイルの削除を行なってからレコードの削除を行うようにしてください。

アップロード画像の削除機能付きアプリ

アップロード画像の削除の手順の解説は以上です。

最後に、アップロード画像の削除機能付きアプリのソースコードを紹介しておきますので、必要な方だけ読み進めていただければと思います。

アプリのソースコード

まず、アプリのソースコードのベースは、下記ページで紹介したアプリのソースコードとさせていただきたいと思います。

Djangoでの画像のアップロードの実現方法解説ページアイキャッチ【Django】画像をアップロードする

そして、このソースコードの upload_project/upload_app/views.py を下記のように変更します。

preview 関数の中で、request.method'POST' である場合に前述の delete 関数を実行するように変更しています(本当は Model 側で delete 関数同等の処理を実現した方が良いかも)。

views.pyの変更

from django.shortcuts import render, get_object_or_404
from .forms import UploadForm
from .models import UploadImage

def index(request):
    params = {
        'title': '画像のアップロード',
        'upload_form': UploadForm(),
        'id': None,
    }

    if (request.method == 'POST'):
        form = UploadForm(request.POST, request.FILES)
        if form.is_valid():
            upload_image = form.save()

            params['id'] = upload_image.id

    return render(request, 'upload_app/index.html', params)

def preview(request, image_id=0):

    upload_image = get_object_or_404(UploadImage, id=image_id)

    if (request.method == 'POST'):
        delete(image_id)

        params = {
            'title': '画像を削除しました',
            'id': image_id,
            'url': None,
        }

        return render(request, 'upload_app/preview.html', params)

    else:
        params = {
            'title': '画像の表示',
            'id': upload_image.id,
            'url': upload_image.image.url
        }

        return render(request, 'upload_app/preview.html', params)

def delete(image_id=0):

    # UploadImageのインスタンスを取得
    upload_image = get_object_or_404(UploadImage, id=image_id)
    
    # 画像ファイルの削除
    upload_image.image.delete()
    
    # レコードの削除
    upload_image.delete()
    

さらに、このソースコードの upload_project/upload_app/templates/upload_app/preview.html を下記のように変更します。削除ボタンが表示されるようにしたり、削除後の画面が表示されたりするように変更しています。

preview.htmlの変更

<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>{{title}}</title>
</head>
<body>
    <h1>{{title}}</h1>
    <div>
        <h2>ID:{{id}}の画像</h2>
        {% if url is not None %}
        <img src="{{url}}">
        <form action="{% url 'preview' id %}" method="post">
            {% csrf_token %}
            <p><input type="submit" value="削除"></p>
        </form>
        {% else %}
        <p>ID:{{id}}の画像は削除されました...</p>
        {% endif %}
    </div>
</body>
</html>

変更は以上のみです。

スポンサーリンク

アプリの動作確認

続いてアップロードされた画像が削除される様子を確認していきましょう!

まずは、下記コマンドを upload_project フォルダで実行し、Django の開発用ウェブサーバーを起動します(Model 変更後にまだマイグレーションを行なっていない方は、ここでマイグレーションも行っておいてください)。

% python manage.py runserver

続いて、ウェブブラウザのアドレスバーに下記 URL を指定し、表示されるページで画像のアップロードを行なって下さい。

http://localhost:8000/upload_app/

アップロードが完了すると ID が表示されるので、その ID を用いてアドレスバーに下記 URL を指定します(ID 部分はご自身で確認した ID を指定して下さい)。

http://localhost:8000/upload_app/preview/ID/

すると、下の図のようなページに遷移し、事前にアップロードした画像が表示されると思います。

アップロードした画像が表示される様子

ここで確認していただきたいのが、upload_project/media/img/ のフォルダの中です。このフォルダの中に、表示中の画像のファイルが存在するはずです。

表示中の画像のファイルが存在する様子

続いて、画像の下にある 削除 ボタンをクリックしてみてください。そうすると、下の図のようなページに遷移するはずです。

アップロードされた画像が削除されたことを示すページが表示される様子

ここで再度 upload_project/media/img/ のフォルダの中を見てみてください。先ほど存在を確認したファイルが削除されていることが確認できるはずです。

表示していた画像のファイルが削除されている様子

この結果から、アップロードされた画像が削除できていることが確認できたことになります。

興味があれば、同様の操作を delete 関数の upload_image.image.delete() 部分を削除してから行なってみてください。

今度は 削除 ボタンを押してもファイルが削除されないことが確認できると思います。このことから、upload_image.image.delete() を実行しないとファイルが削除されないことを理解していただけると思います。

まとめ

このページでは、Django でのアップロードされた画像の削除の仕方について解説しました!

ImageField を持つ Model のインスタンスに delete メソッドを実行させた場合、削除されるのはレコードのみです。

画像ファイルを削除しないとアップロードされた画像が残り続けることになり、ディスクを圧迫することになってしまいますので注意してください。

このページで解説した内容を参考にしていただければ、アップロードさえ実現しておけば簡単に削除も実現できますので、アップロードを行うアプリを開発する際は、是非このページで紹介した手順を参考にしていただければと思います!

同じカテゴリのページ一覧を表示

コメントを残す

メールアドレスが公開されることはありません。