こんにちは宮川です。
2025年5月20日、100日チャレンジもついに21日目!あっという間に3週間が経過しました。 本日は、開発中のミニブログシステムにおいて、カテゴリ編集機能をさらに使いやすく、そして見た目もリッチにするための機能強化に取り組みました。具体的には、カテゴリごとにOGP (Open Graph Protocol) 画像を設定できるように、画像のアップロード機能(トリミング機能付き)を実装しました。
本日の目標
- カテゴリ編集機能におけるOGP画像のアップロード機能(トリミング機能付き)の実装
- 実装に伴うカテゴリ編集機能の動作テストと調整
実装した機能の詳細
今回実装したOGP画像アップロード機能は、フロントエンドとバックエンドの連携が鍵となります。
フロントエンド (HTML, JavaScript, Cropper.js)
ユーザーが直感的に画像をトリミングできるよう、JavaScriptライブラリ「Cropper.js」を導入しました。
- ライブラリ導入:
edit_category.html
テンプレートに Cropper.js の CSS および JS を読み込み。 - フォーム拡張: カテゴリ編集フォームに、OGP画像用のファイル選択 (
<input type="file">
)、画像プレビューエリア、そしてトリミングデータをバックエンドに送るための隠しフィールドを追加。 - JavaScript処理:
- ユーザーが画像ファイルを選択すると、即座にプレビュー表示。
- Cropper.js を初期化し、プレビュー画像上にトリミング枠を表示。
- トリミング枠のアスペクト比は、OGPで推奨される 1200px × 630px (約1.91:1) に固定。これにより、SNSなどでシェアされた際の見栄えを最適化します。
- ユーザーがトリミング範囲を調整すると、その座標データ(x, y, width, heightなど)をリアルタイムで隠しフィールドにセットし、フォーム送信時にサーバーへ送られるようにしました。
バックエンド (Flask, Pillow)
Flask側では、アップロードされた画像とトリミング情報を受け取り、実際に画像を加工して保存します。
- ルーティング処理修正:
admin.py
内のedit_category
ルートを修正。 - データ取得: フォームからアップロードされた画像ファイルと、フロントエンドから送られてきたトリミング座標データを取得。
- 画像トリミング: Pythonの画像処理ライブラリ Pillow を使用し、受け取った座標データに基づいて元画像をトリミング。
- 画像保存: トリミング後の画像をサーバーの指定ディレクトリ (
category_ogp
) に、一意なファイル名で保存。 - データベース更新: 保存したトリミング後画像のパスを、
Category
モデルのogp_image
フィールドに記録。
立ちはだかった壁と乗り越えた道のり
開発はいつも順風満帆とはいきません。今回もいくつかの問題に直面しましたが、一つひとつ解決していきました。
jinja2.exceptions.TemplateNotFound: _flash_messages.html
との遭遇- 原因: Flaskのflashメッセージを表示するための共通テンプレート
_flash_messages.html
が、include
文で指定された場所に見つからないというエラー。 - 解決策:
_flash_messages.html
ファイルがtemplates
ディレクトリ直下に正しく配置されているか、そしてinclude
パスが適切であるかを確認し、修正しました。基本的な部分ですが、見落としやすいポイントです。
- 原因: Flaskのflashメッセージを表示するための共通テンプレート
- 画像アップロード時の
Request Entity Too Large
エラー- 原因: アップロードしようとした画像のファイルサイズが、Flaskアプリケーションのデフォルトのリクエストサイズ上限を超えていたため発生。
- 解決策: Flaskアプリケーションの設定ファイル (
app.py
など) にapp.config['MAX_CONTENT_LENGTH']
を設定し、許容するリクエストサイズの上限を引き上げることで対応しました。今回は16MBに設定しました。
- Cropper.js のトリミング枠が表示されない!最大の難関
- 原因: これが一番時間を要した問題でした。Cropper.jsを導入し、HTMLやJavaScriptの記述も問題なさそうなのに、なぜかトリミング枠が表示されない…。途方に暮れかけましたが、こういう時こそブラウザの**開発者ツール(コンソールログ)**です。 ログを確認すると、Cropper.jsの
<script>
タグに設定していたintegrity
属性のハッシュ値が、CDN上の実際のファイルと一致しておらず、ブラウザによってスクリプトの実行がブロックされていたことが判明しました。 - 解決策:
integrity
属性の値を正しいものに修正(または、開発中は一時的に削除して動作確認)することで、無事 Cropper.js が読み込まれ、トリミング枠が表示されるようになりました!開発者ツールのありがたみを改めて実感した瞬間でした。
- 原因: これが一番時間を要した問題でした。Cropper.jsを導入し、HTMLやJavaScriptの記述も問題なさそうなのに、なぜかトリミング枠が表示されない…。途方に暮れかけましたが、こういう時こそブラウザの**開発者ツール(コンソールログ)**です。 ログを確認すると、Cropper.jsの
現在の状況と今後の展望
お陰様で、カテゴリ編集機能におけるOGP画像のアップロードとトリミングの基本的な枠組みは実装完了しました! ファイル選択 → プレビュー表示 → トリミング枠表示 → フォーム更新によるサーバーでのトリミング処理と保存、という一連の流れは確認できています。
しかし、まだまだやることはあります。
- 残課題:
- トリミング機能の詳細な動作テスト(様々な画像サイズ、ファイル形式、エッジケースでの挙動確認)
- エラーハンドリングの強化(不正なファイル形式のアップロード、画像処理中のエラーなどへの対応)
- 既存OGP画像の扱い(新しい画像をアップロードした際に、古い画像ファイルをサーバーから削除する処理など)
- ユーザーインターフェースの微調整(例: トリミング確定後のプレビュー表示をより分かりやすくするなど、必要に応じて)