8
7

【Django】herokuでCloudinaryを使い画像をアップロードする

Last updated at Posted at 2021-09-15

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が必要なので入ってなければ入れておく。

terminal
$ pip install Pillow

次にCloudinaryのパッケージを入れる。

terminal
$ pip install django-cloudinary-storage

#動画の場合は
$ pip install django-cloudinary-storage[video]

requirements.txtに書き込む。

terminal
$ pip freeze > requirements.txt

Djangoに設定する

まずはINSTALLED_APPSに追加する。

setting.py
#メディアファイルのみの場合
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
#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」に入力します。

あとはパスの設定

setting.py
MEDIA_URL = '/media/'
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'

これで画像がアップできるようになります。

モデルでのフィールド

ImageFieldを使った通常通りの書き方でOKです!

models.py
class TestModel(models.Model):
    name = models.CharField(max_length=10)
    image = models.ImageField(upload_to="image/", blank=True)

テンプレート

他同様.image.urlでインスタンス化できます。

html
<img src = "{{ test_model_instance.image.url }}">

ユーザーがアップロードした元のサイズで画像がダウンロードされるのでコントロールしたい場合は、

html
{% load cloudinary %}

<!-- 画像を挿入したい場所に -->
{% cloudinary test_model_instance.image.name width=100 height=100 %}

.image.urlでなく.image.nameなので注意。

これで100 × 100のサイズが読み込まれるようになります。

さらに、絶対パスを使いたい場合は以下のようにURLを作ります。

html
<img src="https://res.cloudinary.com/<your_cloud_name>/image/upload/c_fill,h_100,w_100/v1/{{ test_model_instance.image.name }}">

絶対パスの取得手順

  1. 適当な画像のURLを取得
  2. 画像のパスを取得
  3. 絶対パスの作成
  4. オプションを設定
html
<!-- 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に記述。

setting.py
CLOUDINARY_STORAGE = {
    #その他の設定
    'EXCLUDE_DELETE_ORPHANED_MEDIA_PATHS':('path/', 'second-path/')
}

引数に除外するパスを書きます。

上記の場合、path/とsecond-path/のメディアファイルは削除しない設定です。

全てを対象とする場合は引数無しでOK。

管理コマンドの実行

本番環境で実行するためheroku runを最初につけます。

terminal
$ 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で実行すると使われていない画像が削除されます。楽ちんだ!

まとめると

setting.py
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で最新の情報を見れます。

8
7
3

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
8
7