メモ帳の構成
プロジェクトの構成
.
-- app.py
-- <instance>
------memo.sqlite メモを保存するデーターベース
-- <templates
------base.html 共通のテンプレート
------list.html メモの一覧テンプレート
------memo.html メモの編集画面テンプレート
メモ帳アプリメインプログラム 削除機能付き
from flask import Flask, request, redirect, url_for, render_template
from flask_sqlalchemy import SQLAlchemy
# Flaskとデータベースの初期化 --- (※1)
app: Flask = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///memo.sqlite"
db:SQLAlchemy = SQLAlchemy(app)
# メモのデータベースモデルを定義
class MemoItem(db.Model):
id: int = db.Column(db.Integer, primary_key=True)
title: str = db.Column(db.Text, nullable=False)
body: str = db.Column(db.Text, nullable=False)
# データベースの初期化
with app.app_context():
db.create_all()
# メモの一覧を表示する --- (※2)
@app.route("/")
def index():
items = MemoItem.query.order_by(MemoItem.title).all()
items.insert(0, {"id": 0, "title": "🖌️ 新規作成", "body": ""})
return render_template("list.html", items=items)
# メモの編集画面を出す --- (※3)
@app.route("/memo/<int:id>", methods=["GET", "POST"])
def memo(id: int):
# IDが0の場合は、データベースを見に行かずに「真っさらな新規データ」を確実に作る
if id == 0:
it = MemoItem(id=0, title="__無題__", body="")
else:
# 既存メモの取得
it = db.session.get(MemoItem, id)
if it is None:
return "メモが見つかりません", 404
# POSTの場合はデータを保存
if request.method == "POST":
it.title = request.form.get("title", "__無題__")
it.body = request.form.get("body", "")
if it.title == "":
return "タイトルは空にできません"
if id == 0:
# 新規保存時:IDをデータベースの自動採番に任せるためNoneにする
it.id = None
db.session.add(it)
db.session.commit()
return redirect(url_for("index"))
# メモの編集画面を表示
return render_template("memo.html", it=it)
# --- ここから追記 ---
@app.route("/memo/<int:id>/delete", methods=["POST"])
def delete_memo(id: int):
it = db.session.get(MemoItem, id)
if it:
db.session.delete(it)
db.session.commit()
return redirect(url_for("index"))
# --- ここまで追記 ---
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8888, debug=True)
共通テンプレート
base.html
<!DOCTYPE html>
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bulma@1.0.2/css/bulma.min.css">
<title>Memo App</title>
</head><body class="p-3">
<div class="p-5 has-background-info"><!-- タイトル -->
<h1 class="is-size-3">Memo App</h1>
</div>
{% block contents %}
<!-- ここに contents が表示される -->
{% endblock %}
</body>
</html>

list.html
<!-- base.html を拡張する -->
{% extends "base.html" %}
<!-- base.html の contents を書き換える -->
{% block contents %}
<div class='card p-3'>
編集したいメモを選んでください:
<ul class='grid'>
{% for it in items %}
<li class="cell card p-4 m-2">
<a href="/memo/{{ it.id }}">
{% if it.id != 0 %}📍{% endif %}
{{ it.title }}
</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
memo.html
<!-- base.html を拡張する -->
{% extends "base.html" %}
<!-- base.html の contents を書き換える -->
{% block contents %}
<div class="card p-3">
<form method="POST">
<label class="label" for="title">タイトル:</label>
<input id="title" name="title" type="text"
value="{{ it.title }}" class="input">
<label class="label" for="body">本文:</label>
<textarea id="body" name="body"
class="textarea">{{ it.body }}</textarea>
<div class="mt-3">
<!-- 保存ボタン -->
<input type="submit" value="保存" class="button is-primary">
<!-- 削除ボタン(新規作成 ID:0 以外の時だけ表示) -->
{% if it.id > 0 %}
<button form="delete-form" type="submit" class="button is-danger is-light"
onclick="return confirm('このメモを本当に削除してもよろしいですか?')">削除</button>
{% endif %}
</div>
</form>
<!-- 削除用の隠しフォーム(セキュリティとレイアウトのため分けて記述します) -->
{% if it.id and it.id > 0 %}
<form id="delete-form" action="{{ url_for('delete_memo', id=it.id) }}" method="POST"></form>
{% endif %}
</div>
{% endblock %}
あ



コメント