
目標
- 共通テンプレートを作成して管理を行いやすくする。
Flaskアプリケーションのレイアウト
共通テンプレートの概要
Flaskでは、Jinja2 というテンプレートエンジンを使用してHTMLを動的に生成します。このとき、複数のページで共通する部分(ヘッダー、フッター、ナビゲーションバーなど)をまとめた、「親テンプレート」と呼ばれる、ひとつのテンプレートを作成し、
「子テンプレート」と呼ばれる個別ページのテンプレートに「継承」して使うことができます。この仕組みによって、コードの重複を減らし、メンテナンスがしやすくなります。
共通テンプレートの実装手順
共通テンプレートの利用は次のような手順で行います。
- 共通テンプレート(base.html)を作成する。
- 共通テンプレートにはヘッダー、ナビゲーションバー、フッターなどを定義します。
- block タグを使い、個別ページごとに内容を差し替え可能にします。
- 個別ページのテンプレート(products.html や categories.html など)で base.html を継承します。
- block の中に、それぞれのページ固有のコンテンツを記述します。

base.htmlの作成
templatesディレクトリの中に、全てのテンプレートで利用されるヘッダーやフッターなどを定義したbase.html(親テンプレート)を作成します。templatesディレクトリを右クリックして新しいファイルを作成し、名前をbase.htmlとします。

base.htmlに次のように入力します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
{% block title %}
<!-- 個別ページのタイトルがここに入る -->
{% endblock %}
</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<header>
{% block header %}
<!-- 個別ページのヘッダーがここに入る -->
{% endblock %}
</header>
<main>
{% block content %}
<!-- 個別ページのコンテンツがここに入る -->
{% endblock %}
</main>
<footer>
<p>© 2025 howahowa store</p>
</footer>
</body>
</html>
manage_products.htmlの編集
base.htmlを継承し、利用するため、manage_products.htmlなどの個別ページではbase.htmlのblockに埋め込む部分だけを準備します。
よって、次のようなbase.htmlでも記述のある部分は削除します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
変更後の manage_products.html は次の通りです。
manage_products.html
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block header %}
<h1>{{ title }}</h1>
<ul>
<li><a href="{{ url_for('product_list') }}" class="button-link">商品一覧</a></li>
<li><a href="{{ url_for('add_product') }}" class="button-link">商品追加</a></li>
<li><a href="{{ url_for('category_list') }}" class="button-link">カテゴリ一覧</a></li>
<li><a href="{{ url_for('add_category') }}" class="button-link">カテゴリ追加</a></li>
</ul>
{% endblock %}
style.css
スタイルシートにheaderタグ、mainタグ、footerタグ部分のスタイルを追加します。
header {
margin: 0;
padding: 10px 0;
}
main {
margin: 0;
padding: 20px;
}
footer {
background-color: #aaa;
color: white;
text-align: center;
padding: 10px 0;
margin-top: 20px;
}
続けてスタイルシートのulセレクタ、ul:first-of-typeセレクタ、ul:first-of-type liセレクタ、liセレクタ部分にheaderを追記し、「header ul」のように編集します。
- ul → header li
- ul:first-of-type → header ul:first-of-type
- ul:first-of-type li → header ul:first-of-type li
- li → header li
/* ボタン部分のリストを横並びにする */
header ul,
main ul {
padding: 0;
}
header ul:first-of-type {
display: flex;
/* 横並び */
justify-content: flex-start;
/* 左寄せ */
}
header ul:first-of-type li {
margin-right: 10px;
/* ボタン間に余白 */
}
/* リストアイテムの基本スタイル */
header li {
list-style-type: none;
/* デフォルトのリストスタイルを削除 */
}
変更後の表示

{% extends “base.html” %}
base.htmlを継承します。(base.htmlを利用可能にします。)
{% block title %}{{ title }}{% endblock %}
base.htmlの次の箇所に取り込まれます。
{% block title %}
<!-- 個別ページのタイトルがここに入る -->
{% endblock %}
{% block header %}{% endblock %}
base.htmlの次の箇所に取り込まれます。
{% block header %}
<!-- 個別ページのコンテンツがここに入る -->
{% endblock %}
products.htmlの編集
products.htmlを次のように編集します。
products.html
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block header %}
<ul>
<li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
<li><a href="{{ url_for('add_product') }}" class="button-link">商品を追加する</a></li>
</ul>
{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
{% for category, products in grouped_products.items() %}
<h2>{{ category }}</h2>
<ul class="product-list">
{% for product in products %}
<li class="product-item">
<span class="product-name">{{ product.name }} : ¥{{ "{:,}".format(product.price) }}</span>
<div class="button-group">
<form action="{{ url_for('edit_product', product_id=product.id) }}" method="GET" style="display:inline;">
<button type="submit" class="edit-button">編集</button>
</form>
<form action="{{ url_for('delete_product', product_id=product.id) }}" method="POST" style="display:inline;">
<button type="submit" class="delete-button"
onclick="return confirm('本当に削除しますか?※既に注文で利用されている場合は削除できません。')">削除</button>
</form>
</div>
</li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}
変更後の表示

products_form.htmlの編集
product_form.html
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block header %}
<ul>
<li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
<li><a href="{{ url_for('product_list') }}" class="button-link">商品一覧に戻る</a></li>
</ul>
{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<form method="POST" action="{{ url_for('add_product') }}">
{{ form.hidden_tag() }} <!-- CSRFトークンを含めるため -->
<label for="product_name">商品名</label>
{{ form.product_name() }} <!-- 商品名入力フィールド -->
{% if form.product_name.errors %}
<ul>
{% for error in form.product_name.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="product_price">価格</label>
{{ form.product_price() }} <!-- 価格入力フィールド -->
{% if form.product_price.errors %}
<ul>
{% for error in form.product_price.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="category">カテゴリー</label>
{{ form.category() }}
{% if form.category.errors %}
<ul>
{% for error in form.category.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<input type="submit" value="商品を登録する">
</form>
{% endblock %}
変更後の表示


categories.htmlの編集
categories.html
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block header %}
<ul>
<li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
<li><a href="{{ url_for('add_category') }}" class="button-link">カテゴリーを追加</a></li>
</ul>
{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<ul>
{% for category in categories %}
<li class="category-item">
<span class="category-name">{{ category.name }}</span>
<div class="button-group">
<form action="{{ url_for('edit_category', category_id=category.id) }}" method="GET">
<button type="submit" class="edit-button">編集</button>
</form>
<form action="{{ url_for('delete_category', category_id=category.id) }}" method="POST">
<button type="submit" class="delete-button"
onclick="return confirm('本当に削除しますか?※既に商品が存在する場合は削除できません。')">削除</button>
</form>
</div>
</li>
{% endfor %}
</ul>
{% endblock %}
変更後の表示

category_form.htmlの編集
category_form.html
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block header %}
<ul>
<li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
<li><a href="{{ url_for('category_list') }}" class="button-link">カテゴリー一覧ページ</a></li>
</ul>
{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<form method="POST">
{{ form.hidden_tag() }}
<label for="name">カテゴリー名</label>
{{ form.name() }}
{% for error in form.name.errors %}
<p style="color: red;">{{ error }}</p>
{% endfor %}
{{ form.submit(class="button-link") }}
</form>
{% endblock %}
変更後の表示

今回は以上になります。

ブックマークのすすめ
「ほわほわぶろぐ」を常に検索するのが面倒だという方はブックマークをお勧めします。ブックマークの設定は別記事にて掲載しています。

