herokuの問題点
herokuは画像がアップロードできない仕様。
AWSなら良いのだけど、herokuの方が管理が楽で安い!
そして無料プランもある!
ってことでCloudinaryを使って実装してみる。
herokuにアドオンを追加
herokuにログインして自分のアプリに移動する。
「Configure Add-ons」→「Find more add-ons」
command + FでCloudinaryを検索。
Image Processingの「Cloudinary - Image and Video Management」内でアドオンを追加できます。
pip
画像を扱うにはPillowが必要なので入ってなければ入れておく。
$ pip install Pillow
次にCloudinaryのパッケージを入れる。
$ pip install django-cloudinary-storage
#動画の場合は
$ pip install django-cloudinary-storage[video]
requirements.txtに書き込む。
$ pip freeze > requirements.txt
Djangoに設定する
まずはINSTALLED_APPS
に追加する。
#メディアファイルのみの場合
INSTALLED_APPS = [
#...
'django.contrib.staticfiles',
'cloudinary_storage',
'cloudinary',
#...
]
#メディアファイル以外がある場合
INSTALLED_APPS = [
#...
'cloudinary_storage',
'django.contrib.staticfiles',
'cloudinary',
#...
]
メディアファイルのみの場合
cloudinary_storageはdjango.contrib.staticfilesより下に置く。
メディアファイル以外の静的ファイルがある場合
django.contrib.staticfilesはcloudinary_storageより下に置く。
※ 公式サイトを参照して下さい
次にCloudinaryのシークレットキーなどを設定。
キー等はCloudinaryのダッシュボードに書いてあります。
#setting.pyの最後に追加でOK
CLOUDINARY_STORAGE = {
'CLOUD_NAME':'your_cloud_name',
'API_KEY': env('CLOUDINARY_API_KEY'),
'API_SECRET': env('CLOUDINARY_API_SECRET')
}
シークレットキーなど公開するべきでないものは.env
ファイルに書いとく。
本番環境でのキー設定は、herokuの「config var」に入力します。
あとはパスの設定
MEDIA_URL = '/media/'
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'
これで画像がアップできるようになります。
モデルでのフィールド
ImageFieldを使った通常通りの書き方でOKです!
class TestModel(models.Model):
name = models.CharField(max_length=10)
image = models.ImageField(upload_to="image/", blank=True)
テンプレート
他同様.image.url
でインスタンス化できます。
<img src = "{{ test_model_instance.image.url }}">
ユーザーがアップロードした元のサイズで画像がダウンロードされるのでコントロールしたい場合は、
{% load cloudinary %}
<!-- 画像を挿入したい場所に -->
{% cloudinary test_model_instance.image.name width=100 height=100 %}
.image.urlでなく.image.nameなので注意。
これで100 × 100のサイズが読み込まれるようになります。
さらに、絶対パスを使いたい場合は以下のようにURLを作ります。
<img src="https://res.cloudinary.com/<your_cloud_name>/image/upload/c_fill,h_100,w_100/v1/{{ test_model_instance.image.name }}">
絶対パスの取得手順
- 適当な画像のURLを取得
- 画像のパスを取得
- 絶対パスの作成
- オプションを設定
<!-- CloudinaryのURLの構造 -->
https://res.cloudinary.com/<cloud_name>/<asset_type>/<delivery_type>/<transformations>/<version>/<public_id>.<extension>
1,実際のURLはこんな感じかと
https://res.cloudinary.com/<your_cloud_name>/image/upload/v1/<ディレクトリ名>/hoge_svqqsy
2,画像のパスを取得
{{ test_model_instance.image.name }}で<ディレクトリ>以降が取得できます。
3,絶対パスの作成
1と2を組み合わせる。
https://res.cloudinary.com/<your_cloud_name>/image/upload/v1/{{ test_model_instance.image.name }}
4,サイズ等オプションの設定
<transformations>の場所に画像のサイズ等の設定を書きます。
https://res.cloudinary.com/<your_cloud_name>/image/upload/h_150,w_150/v1/{{ test_model_instance.image.name }}
Cloudinaryの便利機能
Cloudinaryにはサイズの変更だけでなく、様々な機能があります。
顔認証などもあり、全てを書くと膨大な量になるので一部だけ紹介。
/c_fill,h_150,w_150/
150×150のサイズでいい感じにフィットさせる。
/c_fill,g_face,h_150,w_150/
顔認証機能で顔にフォーカス
詳しく知りたい方は公式ページでご確認ください。
使われていない画像の削除
Cloudinaryには、未使用画像の一括削除という非常に便利な機能があります。
django-cloudinary-storage
の場合管理コマンドは次の3つのみ。
collectstatic
deleteorphanedmedia
deleteredundantstatic
不要なメディアファイルの削除はdeleteorphanedmedia
使えるようにするためsetting.pyに記述。
CLOUDINARY_STORAGE = {
#その他の設定
'EXCLUDE_DELETE_ORPHANED_MEDIA_PATHS':('path/', 'second-path/')
}
引数に除外するパスを書きます。
上記の場合、path/とsecond-path/のメディアファイルは削除しない設定です。
全てを対象とする場合は引数無しでOK。
管理コマンドの実行
本番環境で実行するためheroku run
を最初につけます。
$ heroku run python manage.py deleteorphanedmedia
5 files will be deleted:
- media/hoge1_g5bg8j
- media/hoge2_h8roax
- media/hoge3_uwhmgw
- media/hoge4_svqqsy
- media/hoge5_nqyljq
If you are sure to delete them, please type 'yes':
yesで実行すると使われていない画像が削除されます。楽ちんだ!
まとめると
INSTALLED_APPS = [
#...
'django.contrib.staticfiles',
'cloudinary_storage',
'cloudinary',
#...
]
#色んな設定
MEDIA_URL = '/media/'
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'
CLOUDINARY_STORAGE = {
'CLOUD_NAME':'your_cloud_name',
'API_KEY': env('CLOUDINARY_API_KEY'),
'API_SECRET': env('CLOUDINARY_API_SECRET')
'EXCLUDE_DELETE_ORPHANED_MEDIA_PATHS':(),
}
herokuはサーバー管理が楽なので本当に良いですね!
django-cloudinary-storageのREADME.mdで最新の情報を見れます。