はじめに:独自ドメイン化の罠
自作のポートフォリオサイトをRenderで運用しています。愛機のNikon D3100で撮った写真をもっとちゃんとした形で見せたくて、ついに独自ドメイン(shinotech78.com)を取得しました。
「設定を変えるだけですぐ終わるだろう」と軽く考えていたのですが、デプロイした瞬間、ギャラリーの画像がすべてリンク切れになり、管理画面のCSSが消え去って白黒のテキストだけになるという大惨事に陥りました。
丸一日かけてログと格闘し、ようやく完全に解決できたので、同じ現象で絶望しているDjango開発者のために備忘録として残します。
起きた現象(バグの症状)
-
ギャラリーの写真が表示されず、ブラウザの検証で見ると
https://res.cloudinary.com/...ではなく、ローカルの/media/photos/...を探しに行ってしまっている。 -
本番環境(
DEBUG = False)にすると、管理画面のCSSが当たらず崩滅する。 -
デプロイ(
Clear build cache & deploy)が途中でエラーになり、新しいコードが反映されない。
原因と解決策(3つの断線)
1. Django 5.0以降のストレージ設定の仕様変更
これまでは settings.py に DEFAULT_FILE_STORAGE を書けばCloudinaryが動いていましたが、Django 5.0以降はこの古い書き方が無視されるようになっていました。
【解決策】
# --- settings.py ---
# 1. ライブラリが内部で参照する古い形式の変数名
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
# 2. Django 5.0以降の最新の設定
STORAGES = {
"default": {
"BACKEND": "cloudinary_storage.storage.MediaCloudinaryStorage",
},
"staticfiles": {
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
},
}
2. WhiteNoise と TinyMCE(リッチテキスト)の衝突
デプロイが途中で Failed になっていた原因はこれでした。 ログをよく見ると、ブログ記事用に導入していた tinymce の内部ファイルが見つからず、CSSを圧縮して配信するライブラリ「WhiteNoise」がエラーを吐いてビルドを強制終了させていました。
3. INSTALLED_APPS の読み込み順
設定も完璧、デプロイも成功したのに、どうしても管理画面のCSSが戻らない。 ここで一番ハマりました。真犯人は settings.py の アプリの並び順 でした。
django-cloudinary-storage は、django.contrib.staticfiles より「上」に書かれていると、「画像(Media)だけでなく、デザイン(Static)の管理権限も強制的に奪い取ってしまう」という仕様がありました。
【解決策】
Cloudinaryを staticfiles より下に移動させるだけでした。
# 修正前(Cloudinaryが暴走する)
INSTALLED_APPS = [
'cloudinary_storage',
'cloudinary',
# ...
'django.contrib.staticfiles',
]
# 修正後(Staticの権限を正しく分離)
INSTALLED_APPS = [
# ...
'django.contrib.staticfiles', # これより【下】に配置する!
'cloudinary_storage',
'cloudinary',
]
おわりに:エラーログは最大のヒント
「直前まで動いていたのに…」という時ほど、実は根本的な環境の違い(今回はDjangoのバージョンや、本番環境化)が隠れていることを痛感しました。
無事にCloudinaryとの通信も開通し、ギャラリーにNikonで撮った写真が綺麗に並んだ時はトライアンドエラーのやりがいを感じました。同じエラーで苦しんでいる人の参考になれば嬉しいです。
