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日:新規作成