Visual StudioとFlaskで作る書籍管理アプリ:書籍管理機能の実装
この記事では、FlaskとSQLiteを用いた、基本的なCRUD処理の勉強もかねて、書籍管理機能の実装をします。
また、Bootstrapを使って、比較的簡単に、それなりにきれいな画面を作っていきます。
この記事で、書籍管理アプリのすべての機能の実装が終わります。
コード全体の概要は『Visual StudioとFlaskで作る書籍管理アプリ:外枠を作る』を参照してください。
CRUD処理の対象となるbookテーブルについては『SQLiteとDB Browser for SQLiteを使ってデータベースを構築する』を参照してください。
この記事はVisual StudioとFlaskで書籍管理アプリを作ってみたという一連の記事の中の1つです。
詳しくは以下の記事も参照してください
・Visual Studioで作ってみたFlaskアプリ
・Visual StudioとFlaskで作る書籍管理アプリ:概要
この記事ではWebアプリの開発を何も知らない人を対象とします。といっても、この記事の著者もWebアプリ開発に明るくありません。自分の勉強の意味も込めて書きました。
誤りが含まれるかもしれませんが、ご容赦ください。何かあれば、ご指摘いただけますと幸いです。
スポンサードリンク
目次
- 書籍一覧の取得処理の実装
- 書籍一覧画面(テンプレート)の作成
- 書籍登録処理の実装
- 書籍更新処理の実装
- 書籍削除処理の実装
- 書籍の存在チェックを行う関数の実装
- 書籍の登録・更新・削除確認画面の作成
- 動作確認
1.書籍一覧の取得処理の実装
書籍一覧の取得処理から実装していきます。
画面への表示の方法は少し工夫がいりますが、データを取得するだけならば、それほど複雑ではありません。
以下のようになります。
@bp.route('/')
@login_required
def index_book():
"""書籍の一覧を取得する"""
# DBと接続
db = get_db()
# 書籍データを取得
user_id = session.get('user_id')
books = db.execute(
'SELECT * FROM book WHERE user_id = ? ORDER BY id DESC', (user_id,)
).fetchall()
# 書籍一覧画面へ遷移
return render_template('book/index_book.html',
books=books,
title='ログイン',
year=datetime.now().year)
今回は、ユーザーに紐づく書籍だけを取得していることに注意してください。
セッションからログインしているユーザーのユーザーIDを取得したうえで、それをSELECT文のWHERE句で使用しています。
2.書籍一覧画面(テンプレート)の作成
書籍一覧画面のテンプレートを先に作成しておきます。
Visual Studioのソリューションエクスプローラーの「templatesフォルダ」を右クリックして『追加』→『新しいフォルダ』として「book」という名前のフォルダを新規追加します。
bookフォルダを右クリックして『追加』→『新しい項目』→『HTMLファイル』と選択して「index_book.html」という名前で保存します。
index_book.htmlは以下のように実装します。
{% extends "layout.html" %}
{% block content %}
<h1 style="margin-bottom:50px">書籍一覧</h1>
{% for category, message in get_flashed_messages(with_categories=true) %}
<div class="{{ category }}">{{ message }}</div>
{% endfor %}
<a class="h3" href="{{ url_for('book.create_book') }}">書籍の新規追加</a>
<table class="table table-hover">
<thead>
<tr>
<th>タイトル</th>
<th>著者・作者</th>
<th>出版社</th>
<th>編集</th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ book.title }}</td>
<td>{{ book.auther }}</td>
<td>{{ book.publisher }}</td>
<td>
<a href="{{ url_for('book.update_book', book_id=book.id) }}">編集</a>|
<a href="{{ url_for('book.delete_book', book_id=book.id) }}">削除</a>
</td>
</tr>
{% else %}
<td>書籍が登録されていません</td>
{% endfor %}
</tbody>
</table>
{% endblock %}
エラーや処理の結果など、何かメッセージを表示するときのために、6~8行目で、「flash」で送られてきたメッセージがあればそれを表示するようにしています。
10行目は書籍の新規追加画面へのリンクです。『url_for』を使うことでURLをべた書きしなくても遷移先を指定できます。
12行目からが、書籍一覧を表示する部分です。テーブルレイアウトを適用するのですが、Bootstrapを使っているので『class=”table table-hover”』と指定するだけで、マウスを載せると色が変わる、ちょっとおしゃれ(?)な表を簡単に作成することができます。
表題を設定した後の22行目からが重要です。ここで、先ほど作った『index_book()』関数から送られてきた『books』を、ループして、1行ずつ表示させています。
また、編集・削除画面へのリンクも併せて入れ込むようにしてあります。『url_for(‘book.update_book’, book_id=book.id)』のようにすることで、例えば書籍ID等任意の引数を設定してやることができます。
書籍が1冊も登録されていなかった時の処理が32~34行目です。「書籍が登録されていません」と表示させておきます。
スポンサードリンク
3.書籍登録処理の実装
書籍の登録処理を実装します。
『Visual StudioとFlaskで作る書籍管理アプリ:ログイン機能の実装』で実装したユーザー登録処理とほぼ同様です。
処理の意味はコメントとして入れておきました。
@bp.route('/create_book', methods=('GET', 'POST'))
@login_required
def create_book():
"""
GET :書籍登録画面に遷移
POST:書籍登録処理を実施
"""
if request.method == 'GET':
# 書籍登録画面に遷移
return render_template('book/create_book.html',
title='書籍の追加',
year=datetime.now().year)
# 書籍登録処理
# ユーザーIDを取得
user_id = session.get('user_id')
# 登録フォームから送られてきた値を取得
title = request.form['title']
auther = request.form['auther']
publisher = request.form['publisher']
# DBと接続
db = get_db()
# エラーチェック
error_message = None
if not title:
error_message = '書籍タイトルの入力は必須です'
if error_message is not None:
# エラーがあれば、それを画面に表示させる
flash(error_message, category='alert alert-danger')
return redirect(url_for('book.create_book'))
# エラーがなければテーブルに登録する
db.execute(
'INSERT INTO book (user_id, title, auther, publisher) VALUES (?, ?, ?, ?)',
(user_id, title, auther, publisher)
)
db.commit()
# 書籍一覧画面へ遷移
flash('書籍が追加されました', category='alert alert-info')
return redirect(url_for('book.index_book'))
4.書籍更新処理の実装
続いて書籍更新処理です。
追加処理と異なるのは、
1.書籍IDをURLから受け取る点→存在しない書籍IDが対象となっていたら、エラーにする
2.書籍更新画面に対して、書籍情報を送らなくてはならない点
3.SQLがINSERTからUPDATEに変わった点
となります。それ以外は大体同じです。
@bp.route('/<int:book_id>/update_book', methods=('GET', 'POST'))
@login_required
def update_book(book_id):
"""
GET :書籍更新画面に遷移
POST:書籍更新処理を実施
"""
# 書籍データの取得と存在チェック
book = get_book_and_check(book_id)
if request.method == 'GET':
# 書籍更新画面に遷移
return render_template('book/update_book.html',
book=book,
title='書籍の編集',
year=datetime.now().year)
# 書籍編集処理
# 登録フォームから送られてきた値を取得
title = request.form['title']
auther = request.form['auther']
publisher = request.form['publisher']
# DBと接続
db = get_db()
# エラーチェック
error_message = None
if not title:
error_message = '書籍タイトルの入力は必須です'
if error_message is not None:
# エラーがあれば、それを画面に表示させる
flash(error_message, category='alert alert-danger')
return redirect(url_for('book.update_book'))
# エラーがなければテーブルに登録する
db.execute(
'UPDATE book SET title=?, auther=?, publisher=? WHERE id=?',
(title, auther, publisher, book_id)
)
db.commit()
# 書籍一覧画面へ遷移
flash('書籍が編集されました', category='alert alert-info')
return redirect(url_for('book.index_book'))
書籍データの存在チェックを行う『get_book_and_check(book_id)』という関数は、後ほど実装します。
書籍の存在チェック機能は書籍削除でも用いますので、流用できるように、切り出しました。
5.書籍削除処理の実装
書籍削除処理です。
追加や登録と違って、書籍の情報はIDだけで済むので、気楽です。
うっかり削除されてしまうのを防ぐために、いったん「削除確認画面」を介してから、削除を実行するようにしています。
@bp.route('/<int:book_id>/delete_book', methods=('GET', 'POST'))
@login_required
def delete_book(book_id):
"""
GET :書籍削除確認画面に遷移
POST:書籍削除処理を実施
"""
# 書籍データの取得と存在チェック
book = get_book_and_check(book_id)
if request.method == 'GET':
# 書籍削除確認画面に遷移
return render_template('book/delete_book.html',
book=book,
title='書籍の削除',
year=datetime.now().year)
# 書籍の削除処理
db = get_db()
db.execute('DELETE FROM book WHERE id = ?', (book_id,))
db.commit()
# 書籍一覧画面へ遷移
flash('書籍が削除されました', category='alert alert-info')
return redirect(url_for('book.index_book'))
6.書籍の存在チェックを行う関数の実装
書籍の存在チェックを行う関数を実装します。
書籍IDを使って書籍データをSELECTして、対象の有無を判定します。
もしも対象がなければエラーにします。
def get_book_and_check(book_id):
"""書籍の取得と存在チェックのための関数"""
# 書籍データの取得
db = get_db()
book = db.execute(
'SELECT * FROM book WHERE id = ? ', (book_id,)
).fetchone()
if book is None:
abort(404, 'There is no such book!!')
return book
7.書籍の登録・更新・削除確認画面の作成
書籍の登録画面などを作成します。
ソリューションエクスプローラーからbookフォルダを右クリックして『追加』→『新しい項目』→『HTMLファイル』と選択して、以下のファイルを作成します。
・create_book.html
・update_book.html
・delete_book.html
書籍の登録画面から作成します。
create_book.htmlのコードです。
{% extends "layout.html" %}
{% block content %}
<h1 style="margin-bottom:50px">書籍の追加</h1>
{% for category, message in get_flashed_messages(with_categories=true) %}
<div class="{{ category }}">{{ message }}</div>
{% endfor %}
<form method="post">
<div class="form-group">
<label>本のタイトル</label>
<input type="text" class="form-control" name="title">
</div>
<div class="form-group">
<label>著者</label>
<input type="text" class="form-control" name="auther">
</div>
<div class="form-group">
<label>出版社</label>
<input type="text" class="form-control" name="publisher">
</div>
<button type="submit" class="btn btn-primary">新規追加</button>
</form>
{% endblock %}
書籍の更新画面です。bookデータを受け取って、フォームにあらかじめ設定しておくという点が、新規登録画面と異なります。あとは大体同じです。
update_book.htmlのコードです。
{% extends "layout.html" %}
{% block content %}
<h1 style="margin-bottom:50px">書籍の編集</h1>
{% for category, message in get_flashed_messages(with_categories=true) %}
<div class="{{ category }}">{{ message }}</div>
{% endfor %}
<form method="post">
<div class="form-group">
<label>本のタイトル</label>
<input type="text" class="form-control" name="title" value="{{ book.title }}">
</div>
<div class="form-group">
<label>著者</label>
<input type="text" class="form-control" name="auther"value="{{ book.auther }}">
</div>
<div class="form-group">
<label>出版社</label>
<input type="text" class="form-control" name="publisher" value="{{ book.publisher }}">
</div>
<button type="submit" class="btn btn-primary">更新</button>
</form>
{% endblock %}
最後は書籍の削除画面です。「本当に削除しますか」と確認をするだけです。気が変わった時のことを考えて、「戻る」リンクを追加しておきました。
delete_book.htmlのコードです。
{% extends "layout.html" %}
{% block content %}
<h1 style="margin-bottom:50px">書籍の削除の確認</h1>
<p>{{ book.title }}を本当に削除しますか?(<a href={{url_for('book.index_book')}}>戻る</a>)</p>
<form method="post">
<button type="submit" class="btn btn-primary">書籍の削除</button>
</form>
{% endblock %}
これで書籍管理アプリのすべての機能が実装されました。
誤りなどあれば、ご指摘いただけると幸いです。
8.動作確認
せっかく作ったので、動かしてみます。Visual StudioでF5キーを押すとアプリが起動されます。
「書籍の新規追加」のリンクを押して、書籍情報を登録していきます。

3冊ほど書籍を登録してみました。
しかし、「書籍無量大数」の出版社名が「思いつかなかった」などという問題のある内容になっていますね。

「書籍無量大数」において、編集のリンクを押して、出版社名を「誤りがあったので修正します」に変更しました。

最後に、存在しない書籍IDを対象にして、更新画面のURLをたたいてみます。
すると、エラーメッセージが表示されます。

これでとりあえずの機能は完成しました。
参考文献
Welcome to Flask
→Flaskの全体像をつかむことができる公式サイトです。ここのチュートリアルを参考にしました。
|
独学プログラマー Python言語の基本から仕事のやり方まで Pythonのことがさっぱりわからないという方は、この本から入ると良いかと思います。あまり分厚くない本ですので、読み切ることは難しくないはずです。 Pythonの基本文法やコードを書くコツなどが載っています。 |
|
|
入門Python3 こちらは分厚い本ですが、その分細かく載っています。Flaskの解説も少しあります。辞書的な使い方をしても良い本かと思います。 |
|
|
演習で力がつく HTML/CSSコーディングの教科書 HTMLとCSSはこの本を読んで勉強しました。 Web開発の書籍はたくさんあるので、お好きなものを選ばれたら良いかなと思います。 |
|
スポンサードリンク
更新履歴
2018年5月26日:新規作成






