2026.06.04(更新日: 2026.06.04)
FastAPIのトップページのルーティングの仕組み
はじめに
My Portfolioは、FastAPIを使用して開発しました。
本記事では、トップページのURL(http://127.0.0.1:8000/)にアクセスしてから、
画面がレンダリングされるまでのソースコードの処理の流れについて書いていきます。
トップページのURLにアクセスしたときにまず起こっていること
こちらのトップページにアクセスした時に、ソースコードでは何が起こっているのでしょうか

まずは、app/routers/top.pyのtop_pageメソッドで画面の取得処理を行っています
from fastapi import Depends, Request
from app import models
from sqlalchemy.orm import Session
from app.database import get_db
from fastapi import APIRouter
from fastapi.templating import Jinja2Templates
router = APIRouter()
templates = Jinja2Templates(directory="app/templates")
@router.get("/")
def top_page(
request: Request,
db: Session = Depends(get_db)
):
user_id = request.session.get("user_id")
role = request.session.get("role")
is_logged_in = "user_id" in request.session
works = (
db.query(models.Work)
.order_by(models.Work.id.desc())
.limit(2)
.all()
)
blogs = (
db.query(models.Blog)
.order_by(models.Blog.published_at.desc())
.limit(2)
.all()
)
recent_careers = (
db.query(models.Career)
.order_by(models.Career.id.desc())
.limit(2)
.all()
)
return templates.TemplateResponse(
request,
"top.html",
{
"works": works,
"blogs": blogs,
"recent_careers": recent_careers,
"user_id": user_id,
"is_logged_in": is_logged_in
}
)
トップページのURLをtop_pageメソッドに登録する
fastapiからAPIRouterをインポートして、routerとしてインスタンスを生成します。そして、top_pageメソッドにトップページのURLを登録します
from fastapi import APIRouter
router = APIRouter()
@router.get("/")
def top_page(
request: Request,
db: Session = Depends(get_db)
):
テンプレートに渡す情報を定義する
次に、トップページのテンプレートファイル(app/templates/top.html)に渡す情報を定義します
以下のような情報です
- ログインしているかどうか(is_logged_in)
- 制作物の情報(works)
- 技術ブログの情報(blogs)
↓ ログインしているかどうか(is_logged_in)
from fastapi import Depends, Request
@router.get("/")
def top_page(
request: Request,
db: Session = Depends(get_db)
):
user_id = request.session.get("user_id")
is_logged_in = "user_id" in request.session
return templates.TemplateResponse(
request,
"top.html",
{
"is_logged_in": is_logged_in
}
)
↓ 制作物の情報(works)
from fastapi import Depends, Request
from app import models
from sqlalchemy.orm import Session
from app.database import get_db
@router.get("/")
def top_page(
request: Request,
db: Session = Depends(get_db)
):
works = (
db.query(models.Work)
.order_by(models.Work.id.desc())
.limit(2)
.all()
)
return templates.TemplateResponse(
request,
"top.html",
{
"works": works,
}
)
↓ 技術ブログの情報
from fastapi import Depends, Request
from app import models
from sqlalchemy.orm import Session
from app.database import get_db
@router.get("/")
def top_page(
request: Request,
db: Session = Depends(get_db)
):
blogs = (
db.query(models.Blog)
.order_by(models.Blog.published_at.desc())
.limit(2)
.all()
)
return templates.TemplateResponse(
request,
"top.html",
{
"blogs": blogs,
}
)
テンプレート(top.html)に値が渡ってくる
app/templates/top.htmlに以下のような値が渡ってきます
- ログインしているかどうか(is_logged_in)
- 制作物の情報(works)
- 技術ブログの情報(blogs)
↓ ログインしているかどうか(is_logged_in)
{% if is_logged_in %}
<a
href="/works-page/new"
class="btn-outline"
>
新規制作物を登録する
</a>
{% endif %}
↓ 制作物の情報(works)
<section class="top-section">
<div class="section-header">
<h2 class="section-title">
最近の制作物
</h2>
<a href="/works-page" class="primary-button view-all-btn view-all-btn-pc">
すべて見る
</a>
</div>
<div class="top-grid">
{% for work in works %}
<a
href="/works-page/{{ work.id }}"
class="work-card"
>
{% if work.image_url %}
<img
src="{% if work.image_url.startswith('/') %}{{ work.image_url }}{% else %}/{{ work.image_url }}{% endif %}"
alt="{{ work.title }}"
class="work-thumbnail"
>
{% endif %}
<h2>
{{ work.title }}
</h2>
<p class="work-description">
{{ work.description }}
</p>
<div class="tech-tags">
{% for tech in work.tech_stack.split(",") %}
<span class="tech-tag">
{{ tech.strip() }}
</span>
{% endfor %}
</div>
</a>
{% endfor %}
</div>
↓ 技術ブログの情報(blogs)
<section class="top-section">
<div class="section-header">
<h2 class="section-title">
最近の技術ブログ
</h2>
<a href="/blogs-page" class="primary-button view-all-btn view-all-btn-pc">
すべて見る
</a>
</div>
<div class="top-grid">
{% for blog in blogs %}
<a
href="/blogs-page/{{ blog.id }}"
class="work-card"
>
<h2>{{ blog.title }}</h2>
<div class="blog-meta">
{% if blog.published_at %}
<span>{{ blog.published_at }}</span>
{% endif %}
</div>
<p class="work-description">
{{ blog.summary }}
</p>
{% if blog.tags %}
<div class="tech-tags">
{% for tag in blog.tags.split(",") %}
<span class="tech-tag">
{{ tag.strip() }}
</span>
{% endfor %}
</div>
{% endif %}
</a>
{% endfor %}
</div>
図にするとこんな感じ(is_logged_inの場合)
①URLからtop_pageメソッドの処理が開始する

②is_logged_in(ログインしているかどうか)がトップページのテンプレート(top.html)に渡される

③ログインしているかどうかによって、新規制作物を登録するボタンの表示・非表示を制御している

コメントを残す