FastAPIで独自のフォーラムを構築する:ステップ4 - ユーザーシステム

要約
このガイドでは、FastAPIフォーラムにユーザー認証システムを追加する方法を詳しく説明します。登録、ログイン、パスワードハッシュ、投稿と作成者の関連付けについて説明します。
意見はこのエリアに表示されます
アイキャッチ画像

前の記事では、Jinja2テンプレートエンジンを使用して、バックエンドのPythonロジックからフロントエンドのHTMLコードを分離し、プロジェクト構造をより明確にしました。

現在のフォーラムでは誰でも匿名で投稿できるため、コミュニティの運営方法としては適切ではありません。フォーラムはユーザーを中心に構築されるべきです。各ユーザーには独自のID、独自の投稿、返信があります。

そこで、この記事では、ユーザー登録、ログイン、ログアウト機能を含む完全なユーザーシステムをフォーラムに追加します。

ステップ1:依存関係のインストール

パスワード暗号化を処理するライブラリが必要です。ユーザーのパスワードは、極めて危険であるため、プレーンテキストで保存することはできません。ここではpasslibpbkdf2_sha256アルゴリズムを使用します。

次のコマンドを実行します。

ステップ2:データベースモデルの更新

ユーザー情報を保存するための新しいテーブルが必要であり、各投稿の作成者を記録するためにpostsテーブルをusersテーブルに関連付ける必要があります。

models.pyファイルを開き、以下の変更を加えます。

models.py(更新版)

ここでは2つのことを行いました。

  • Userモデルの作成
    • id、一意のusernamehashed_passwordフィールドを含むusersテーブルを定義します。
  • PostUserの関連付け
    • Postモデルに、usersテーブルのidを指す外部キーとしてowner_idフィールドを追加しました。
    • SQLAlchemyのrelationshipを使用して、PostUserの間に双方向の関連付けを確立しました。これで、post.ownerを通じて投稿の作成者にアクセスでき、user.postsを通じてユーザーのすべての投稿にアクセスすることもできます。

これらのモデルを適用する前に、データベースを手動で更新する必要があります。usersテーブルを作成し、postsテーブルを変更する必要があります。

対応するSQLステートメントは次のとおりです。

Leapcellを使用してデータベースを作成した場合、

ImageLc

そのWebベースの操作パネルでこれらのSQLステートメントを直接実行できます。

ImageDb

ステップ3:パスワードの処理

新しいファイルauth.pyを作成し、パスワードハッシュ化および検証用の関数を記述して、パスワードを安全に処理します。

auth.py

  • verify_password:ユーザーが入力したプレーンテキストパスワードとデータベースに保存されているハッシュ化されたパスワードを比較して、一致するかどうかを確認します。
  • get_password_hash:プレーンテキストパスワードをハッシュ値に変換して、データベースに保存できるようにします。

ステップ4:ユーザー登録およびログインページの作成

posts.htmlと同様に、templatesフォルダ内にregister.htmllogin.htmlという2つの新しいHTMLファイルを作成します。

templates/register.html

templates/login.html

ステップ5:認証関連のAPIルートの実装

main.pyをリファクタリングして、登録、ログイン、ログアウト、および現在のユーザー状態管理機能を追加します。これは比較的大きな更新です。

main.py(最終完全版)

このファイルは主にこれらの変更を行いました。

  1. get_current_user関数の追加:この関数は、リクエスト内のforum_userCookieを読み取って現在のユーザーを識別します。後続のルートでは、Depends(get_current_user)を通じてログイン中のユーザー情報を直接取得できます。
  2. ユーザー登録およびログイン関連ルートの追加
    • 登録(/register:GETリクエストは登録フォームを表示し、POSTリクエストはフォーム送信を処理します。ユーザー名が既に存在するかどうかを確認し、パスワードをハッシュ化してデータベースに保存します。
    • ログイン(/login:GETリクエストはログインフォームを表示します。POSTリクエストは、ユーザー名とパスワードを検証します。成功した場合、レスポンスにforum_userという名前のCookieを設定し、ユーザー名を値として設定します。これはシンプルなセッション実装です。
    • ログアウト(/logoutforum_userCookieをクリアし、ホームページにリダイレクトします。
  3. ルート保護create_postルートは、get_current_userに依存するようになりました。ユーザーがログインしていない場合、ログインページにリダイレクトされます。投稿時、投稿のowner_idは自動的に現在ログインしているユーザーのIDに設定されます。
  4. ビューの更新/postsなどのルートは、現在のユーザー情報を取得し、テンプレートに渡して、ページにログイン状態を表示できるようにします。

ステップ6:ホームページテンプレートを更新してユーザー状態を表示する

最後に、templates/posts.htmlを修正して、ユーザーのログイン状態に基づいて異なるコンテンツを表示できるようにします。

templates/posts.html(更新版)

テンプレートは主にこれらの変更を行いました。

  • 上部のナビゲーションは、ログイン状態を判断するために{% if current_user %}を使用します。ユーザーがログインしている場合、ウェルカムメッセージと「Logout」リンクが表示されます。それ以外の場合は、「Login」と「Register」リンクが表示されます。
  • 新しい投稿用のフォームは、ログイン中のユーザーのみが表示できるように制限されています。
  • 各投稿の下部に、{{ post.owner.username }}を通じて作成者のユーザー名が表示されます。

実行と検証

結果を確認する時です!uvicornサーバーを再起動します。

http://127.0.0.1:8000にアクセスします。ホームページの右上隅に「Login」と「Register」リンクが表示され、ページに投稿を作成するエントリはありません。

ImageP1

新しいユーザーを登録し、ログインしてみてください。ログイン後、投稿フォームが表示され、ページの上部にユーザー名が表示されます。

ImageP2

投稿を送信すると、その作成者は正しくあなたのユーザー名として表示されます。

ImageP3

まとめ

この記事を通じて、フォーラムのユーザーシステムを構築しました。これで、誰もが登録、ログイン、そして自分の投稿を公開できます。

投稿にユーザーが紐づいた後、次のことを検討できます。もしユーザーが自分で公開した投稿の内容を変更したい場合はどうなるでしょうか?

次の記事では、現在のユーザーシステムに基づいた新しい機能、つまりユーザーが既に作成した投稿を編集できるようにする機能を実装します。


Xでフォローする:@LeapcellJapan


ブログでこの記事を読む

関連記事:

Explore More
関連記事はありません。