このページでは、Django でのアップロードされた画像の削除の仕方について解説していきます。
下記ページで画像のアップロードについて解説していますが、今回は逆にアップロードされた画像のファイルを削除する手順を解説していきます。
【Django】画像をアップロードするといっても、画像のアップロードさえ実現できていれば、アップロードされた画像のファイルの削除も簡単に実現できます。
ただ、ちょっと注意点があるので、その辺りを中心に解説させていただきたいと思います。
申し訳ありませんが、ImageField
を用いた画像のアップロード手順をご存知であることを前提に解説させていただきますので、画像のアップロード手順をご存知ない方は、まずは上記ページでその手順について理解しておいていただければと思います。
Contents
アップロードされた画像の削除
では、アップロードされた画像の削除の仕方について解説していきます。
アップロードされた画像の削除における注意点
下記ページの 画像アップロード用の Model の作成 でも解説していますが、ImageField
を持つ Model のインスタンスに save
メソッドを実行させた場合、レコードの保存だけでなくアップロードされた画像のファイル保存も行われます。
それに対し、ImageField
を持つ Model のインスタンスに delete
メソッドを実行させた場合、削除されるのは save
メソッド実行時に保存された “レコードのみ” です。
つまり、ImageField
を持つ Model のインスタンスに delete
メソッドを実行させても、保存された画像ファイルは削除されません。
なので、保存された画像ファイルの削除に関しては、レコードの削除とは別に行う必要があります。
その保存された画像ファイルの削除は、ImageField
のインスタンスに delete
メソッドを実行させることで行うことができます。
実際には、delete
メソッドを実行するのは ImageFieldFile
のインスタンスとなります
が、今回は簡単のため、ImageField
のインスタンスが delete
メソッドを実行する前提で解説をさせていただきます
スポンサーリンク
アップロードされた画像を削除する手順
ですので、アップロードされた画像を削除する際には下記のような手順を踏むことになります。
- 削除したい画像に対応する Model のインスタンスを取得する
- Model のインスタンスの
ImageField
のデータ属性にdelete
メソッドを実行させる
アップロードされた画像だけでなく、その画像に対応するレコードもデータベースから削除したい場合は下記の手順も必要になります。
- Model のインスタンスに
delete
メソッドを実行させる
例えば、ImageField
持つ Model を下記の UploadImage
とした時、
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】画像をアップロードするそして、このソースコードの upload_project/upload_app/views.py
を下記のように変更します。
preview
関数の中で、request.method
が 'POST'
である場合に前述の delete
関数を実行するように変更しています(本当は Model 側で delete
関数同等の処理を実現した方が良いかも)。
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
を下記のように変更します。削除ボタンが表示されるようにしたり、削除後の画面が表示されたりするように変更しています。
<!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
メソッドを実行させた場合、削除されるのはレコードのみです。
画像ファイルを削除しないとアップロードされた画像が残り続けることになり、ディスクを圧迫することになってしまいますので注意してください。
このページで解説した内容を参考にしていただければ、アップロードさえ実現しておけば簡単に削除も実現できますので、アップロードを行うアプリを開発する際は、是非このページで紹介した手順を参考にしていただければと思います!