前の記事では、FastAPIブログにコメント返信機能を実装し、コメントセクションのインタラクティブ性を大幅に向上させました。
現在、投稿とコメントの機能はかなり充実していますが、投稿自体はプレーンテキストしかサポートしておらず、少し単調です。
この記事では、投稿に画像アップロード機能を追加し、ブログコンテンツをテキストと画像の両方でリッチにし、より表現力豊かにします。
画像アップロードを実装する原則は次のとおりです。
- ユーザーはフロントエンドページで画像を選択してアップロードします。
- バックエンドは画像を受信し、オブジェクトストレージサービスに保存します。
- バックエンドは画像の公開URLを返します。
- フロントエンドはこのURLをMarkdown形式(

)で投稿のコンテンツテキストボックスに挿入します。 - 投稿コンテンツが最終的にウェブページとしてレンダリングされると、ブラウザはこのURLを使用して画像を取得し、表示します。
ステップ1:S3互換オブジェクトストレージの準備
まず、ユーザーがアップロードした画像を保存する場所が必要です。サーバーのハードドライブに直接保存することもできますが、最新のWebアプリケーションでは、オブジェクトストレージサービス(AWS S3など)を使用することをお勧めします。メンテナンスが容易で、スケーラビリティが高く、コスト効率も良いためです。
利便性のために、データベースとバックエンドホスティングを提供するだけでなく、S3互換のオブジェクトストレージサービスも提供するLeapcellを引き続き使用します。

Leapcellのメインインターフェイスにログインし、「オブジェクトストレージの作成」をクリックします。

名前を入力してオブジェクトストレージを作成します。

オブジェクトストレージの詳細ページで、エンドポイント、アクセスキーID、シークレットアクセスキーなどの接続パラメータが表示されます。これらは後でバックエンド設定で使用します。

インターフェイスには、ブラウザで直接ファイルをアップロードおよび管理するための非常に便利なUIも用意されています。

ステップ2:バックエンドでの画像アップロードAPIの実装
次に、ファイルアップロードを処理するFastAPIバックエンドを構築しましょう。
1. 依存関係のインストール
S3互換オブジェクトストレージサービスにファイルをアップロードするには、boto3
(Python用のAWS SDK)が必要です。さらに、投稿を表示する際にMarkdown形式をHTMLに変換するために、Markdown解析ライブラリが必要です。ここではmarkdown2
を選択します。
これらをrequirements.txt
ファイルに追加します。
次に、インストールコマンドを実行します。
2. アップロードサービスの作成
コードをクリーンに保つために、ファイルアップロード機能用の新しいサービスファイルを作成します。
プロジェクトのルートディレクトリに新しいファイルuploads_service.py
を作成します。このサービスは、S3との通信のコアロジックを担当します。
注意: 実装を簡略化するために、S3接続パラメータはハードコーディングされています。実際のプロジェクトでは、この機密情報を環境変数に保存し、os.getenv()
を使用して読み込むことを強くお勧めします。
3. アップロードルートの作成
次に、APIルートを定義するために、routers
フォルダに新しいファイルuploads.py
を作成しましょう。
最後に、この新しいルーターモジュールをメインアプリケーションmain.py
にマウントします。
ステップ3:フロントエンドでのFilePicker APIの統合
バックエンドの準備ができたので、new-post.html
フロントエンドページを変更してアップロード機能を追加しましょう。
アップロードを処理するには、モダンなFilePicker APIと従来の<input type="file">
の2つの方法があります。
従来のメソッド:<input type="file">
は優れた互換性を持ち、すべてのブラウザでサポートされています。ただし、APIはやや時代遅れで、直感的ではなく、ユーザーエクスペリエンスが悪いです。
モダンなメソッド:File System Access APIは使いやすく、強力で、より良いユーザーエクスペリエンスにつながります。ただし、互換性は従来のメソッドほどではなく、セキュアなコンテキスト(HTTPS)で実行する必要があります。
私たちのブログはモダンなプロジェクトであるため、FilePicker APIを使用してファイルアップロードを実装します。
templates/new-post.html
を開き、textarea
の上にツールバーと「画像のアップロード」ボタンを追加します。
ステップ4:画像を含む投稿のレンダリング
画像へのMarkdownリンクを投稿コンテンツに挿入できましたが、まだテキスト文字列としてレンダリングされるだけです。投稿詳細ページpost.html
で、Markdown形式を実際のHTMLに変換する必要があります。
1. ルートでのMarkdown解析
routers/posts.py
のget_post_by_id
関数を変更します。投稿データをテンプレートに渡す前に、markdown2
でコンテンツを解析します。
2. 投稿詳細ページビューの更新
最後に、templates/post.html
を変更して、解析されたHTMLが正しくレンダリングされるようにします。以前は、改行を処理するためにを使用していました。コンテンツがすでにHTMLになっているため、safe
フィルターを使用するだけで済みます。
safe
フィルターは、Jinja2にこの変数のコンテンツが安全であり、HTMLエスケープする必要がないことを伝えます。これにより、画像<img>
タグやその他のMarkdownフォーマットが正しくレンダリングされます。
実行とテスト
これで、アプリケーションを再起動します。
ログイン後、「新規投稿」ページに移動すると、新しい「画像のアップロード」ボタンが表示されます。それをクリックしてアップロードするファイルを選択します。
画像を選択します。アップロードが完了すると、画像のMarkdownリンクがテキストボックスに自動的に挿入されます。

投稿を発行し、投稿詳細ページに移動します。画像が正常にレンダリングされていることがわかります。さらに、投稿コンテンツはMarkdown構文をサポートするようになりました!

おめでとうございます。ブログで画像(およびMarkdown)のアップロードがサポートされるようになりました!これからは、あなたのブログは間違いなくはるかにエキサイティングになるでしょう。
Xでフォローする:@LeapcellJP
関連記事: