コンテンツへスキップ

Django 3.x から 5.x へアップグレードしたらS3の画像が表示されなくなった時の対処法

Django 3.x から 5.x へアップグレードしたらS3の画像が表示されなくなった時の対処法

Django プロジェクトを 3.x 系から 4.x や 5.x といった新しいバージョンにアップグレードした際、「あれ? S3 に保存してある画像が表示されなくなった!」と焦った経験はありませんか?

特に django-storages を使って AWS S3 にメディアファイルや静的ファイルを置いている場合、今回の問題に遭遇する可能性が高いです。

具体的には、以下のような**FileNotFoundError**を目にするかもしれません。

FileNotFoundError at /your_app/some_page/
[Errno 2] No such file or directory: '/path/to/your/project/media/images/sample_image.jpeg'
Request Method: GET
Request URL: https://www.yourdomain.com/your_app/some_page/
Django Version: 5.x.x
Exception Type: FileNotFoundError
Exception Value: [Errno 2] No such file or directory: '/path/to/your/project/media/images/sample_image.jpeg'

このエラーは、Django が指定されたパスにファイルを見つけられないことを示しています。これは、本来S3を参照すべきところが、誤ってサーバーのローカルファイルシステムを参照しようとしてしまっている場合などに発生します。この記事では、この問題の最も一般的な原因と、その解決策を分かりやすく解説します。

特に django-storages を使って AWS S3 にメディアファイルや静的ファイルを置いている場合、今回の問題に遭遇する可能性が高いです。この記事では、この問題の最も一般的な原因と、その解決策を分かりやすく解説します。


問題の背景:Django 4.2 でのストレージ設定の変更

Django 4.2 以降、ファイルストレージの設定方法が大きく変わりました。以前は settings.pyDEFAULT_FILE_STORAGESTATICFILES_STORAGE といった設定項目に直接ストレージバックエンドを指定していましたが、新しいバージョンではこれらが非推奨となり、STORAGES ディクショナリを使って一元管理する方式が導入されました。

そのため、古いバージョンの設定をそのまま引き継いでしまうと、Django がS3上のファイルを正しく認識できず、「ファイルが見つかりません」というエラー (FileNotFoundError) が発生したり、画像リンクが壊れて表示されなくなったりするのです。


解決策:settings.pySTORAGES ディクショナリへの移行

この問題を解決するには、settings.py 内のファイルストレージに関する設定を、新しい STORAGES ディクショナリ形式に移行する必要があります。

1. 古いストレージ設定の削除またはコメントアウト

まず、settings.py から以下の古い設定行を見つけて、削除するかコメントアウトしてください。

Python

# settings.py

# これらの行を削除するか、コメントアウトしてください
# STATICFILES_STORAGE = 'your_app.storage.CustomS3Boto3Storage'
# DEFAULT_FILE_STORAGE = 'your_app.storage.CustomS3Boto3Storage'

'your_app.storage.CustomS3Boto3Storage' の部分は、ご自身のカスタムストレージクラスのパスに読み替えてください。

2. 新しい STORAGES ディクショナリの追加

次に、settings.py に以下の STORAGES ディクショナリを追加します。これにより、Django は新しい方法でファイルストレージを管理するようになります。

Python

# settings.py

STORAGES = {
    "default": {
        "BACKEND": "your_app.storage.CustomS3Boto3Storage",
        # もし必要であれば、ここに S3Storage の追加オプションを辞書形式で渡せます。
        # 例: "OPTIONS": {"location": "media/", "default_acl": "public-read"},
    },
    "staticfiles": {
        "BACKEND": "your_app.storage.CustomS3Boto3Storage",
        # 静的ファイル用のオプションも必要であれば追加します。
        # 例: "OPTIONS": {"location": "static/", "default_acl": "public-read"},
    },
    # 必要に応じて、他のカスタムストレージやキャッシュストレージもここに追加できます。
}

ここでも 'your_app.storage.CustomS3Boto3Storage' は、ご自身のカスタムストレージクラスのパスに置き換えてください。

3. 既存の AWS 関連設定はそのまま維持

AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_STORAGE_BUCKET_NAMEAWS_S3_REGION_NAME といったS3への接続に必要な情報は、引き続きsettings.pyのトップレベルにそのまま残しておいてください。これらの設定は、STORAGES ディクショナリで指定された S3 バックエンドに自動的に適用されます。

Python

# settings.py (これらの設定はそのまま残します)

AWS_ACCESS_KEY_ID = 'YOUR_ACCESS_KEY'
AWS_SECRET_ACCESS_KEY = 'YOUR_SECRET_KEY'
AWS_STORAGE_BUCKET_NAME = 'your-s3-bucket-name'
AWS_S3_REGION_NAME = 'ap-northeast-1'
# ... その他の AWS 設定 (AWS_S3_FILE_OVERWRITE, AWS_DEFAULT_ACL, AWS_LOCATION など)

4. カスタムストレージクラスのコードは残す

今回の問題は設定ファイルの変更が主な原因であり、あなたが作成した CustomS3Boto3Storage クラス自体は、S3へのファイル保存ロジックをカスタマイズする重要な部分です。このクラスの定義ファイルは削除せずに、そのまま残しておいてください


まとめ

Django 3.x から 5.x へのアップグレードでS3の画像が表示されなくなった場合、ほとんどの原因は settings.py におけるファイルストレージ設定の変更によるものです。上記の手順で STORAGES ディクショナリへの移行を行えば、スムーズに問題が解決し、新しいDjangoバージョンでもS3上の画像がしっかり表示されるようになるはずです。

もしこの変更後も問題が続く場合は、S3バケットのパーミッション設定や、django-storagesのバージョンが最新であるかなども確認してみてください。

これで、あなたのDjangoプロジェクトも最新バージョンでバッチリ動くようになるでしょう!