モブプロだった人のブログ

モブプログラミングに魅了されたエンジニアのブログ

Flask + Flask-SQLAlchemy のチュートリアルを日本語で (Bootstrap 編)

チュートリアル関連記事

はじめに

今回は、番外編として見た目を整えたいと思います。見た目がそれなりにキレイだと、プログラミングもやる気が出ますよね!(個人差は確実にあります。)

それでは、Bootstrap を使っていきます。

f:id:kaorr_mob:20171129003343j:plain

各ファイルの作成・修正・削除

Python ファイル修正

hello.py ファイルを以下のようの修正します。

from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///hello.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)

    def __init__(self, username):
        self.username = username


@app.route("/")
def top():
    user_list = User.query.all()
    return render_template('top.html', title='ユーザ一覧', user_list=user_list)

@app.route("/add_user", methods=['POST'])
def add_user():
    username = request.form.get('username')
    if username:
        user = User(username)
        db.session.add(user)
        db.session.commit()

    return redirect(url_for('top'))

@app.route("/user/<int:user_id>", methods=['GET'])
def show_user(user_id):
    target_user = User.query.get(user_id)

    return render_template('show.html', title='ユーザ詳細', target_user=target_user)

@app.route("/user/<int:user_id>", methods=['POST'])
def mod_user(user_id):
    target_user = User.query.get(user_id)
    username = request.form.get('username')
    if target_user and username:
        target_user.username = username
        db.session.commit()

    return redirect(url_for('top'))

@app.route("/del_user/<int:user_id>", methods=['POST'])
def del_user(user_id):
    target_user = User.query.get(user_id)
    if target_user:
        db.session.delete(target_user)
        db.session.commit()

    return redirect(url_for('top'))

if __name__ == '__main__':
    app.run(debug=True)
  • render_template に title を追加
  • hello を top に変更

HTML(Jinja2 テンプレート) ファイル作成

templates/layout.html ファイルを以下のように作成します。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <title>{{ title }}</title>
</head>
<body>
  <nav class="navbar navbar-inverse">
    <div class="container-fluid">
      <div class="navbar-header">
        <a class="navbar-brand" href="{{ url_for('top') }}">Flask + Flask-SQLAlchemy チュートリアル</a>
      </div>
    </div>
  </nav>
  <div class="container">
    {% block content %}{% endblock %}
  </div>
</body>
</html>
  • このファイルは、各ページの継承元になる
  • {% block content %}{% endblock %} の箇所に、各ページでコンテンツを埋め込む

HTML(Jinja2 テンプレート) ファイル修正

templates/hello.html ファイルを templates/top.html に変更し、以下のように修正します。

{% extends 'layout.html' %}
{% block content %}
  <h1>{{ title }}</h1>
  <table class="table">
    <thead>
      <tr>
        <th>ID</th>
        <th>名前</th>
        <th>詳細</th>
      </tr>
    </thead>
    <tbody>
      {% for user in user_list %}
      <tr>
        <td>{{ user.id }}</td>
        <td>{{ user.username }}</td>
        <td>
          <a class="btn btn-success" href="{{ url_for('show_user', user_id=user.id) }}">
            <span class="glyphicon glyphicon-search" aria-hidden="true"></span> 詳細
          </a>
      </td>
      </tr>
      {% endfor %}
    </tbody>
    </table>
  <form action="{{ url_for('add_user') }}" method="post" class="form-inline">
    <label for="username">Name</label>
    <input type="text" class="form-control" id="username" name="username">
    <button type="submit" class="btn btn-primary">
      <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> 追加
    </button>
  </form>
{% endblock %}

templates/show.html ファイルを以下のように修正します。

{% extends 'layout.html' %}
{% block content %}
  <h1>{{ title }}</h1>
  <form action="{{ url_for('mod_user', user_id=target_user.id) }}" method="post" class="form-horizontal">
    <div class="form-group">
      <label for="user_id" class="col-sm-2 control-label">ID</label>
      <div class="col-sm-10">
        <input type="text" class="form-control" id="user_id" value="{{ target_user.id }}" disabled>
      </div>
    </div>
    <div class="form-group">
      <label for="username" class="col-sm-2 control-label">名前</label>
      <div class="col-sm-10">
        <input type="text" class="form-control" id="username" name="username" value="{{ target_user.username }}">
      </div>
    </div>
    <div class="form-group">
      <div class="col-sm-offset-2 col-sm-10">
        <button type="submit" class="btn btn-primary">
          <span class="glyphicon glyphicon-cog" aria-hidden="true"></span> 変更
        </button>
      </div>
    </div>
  </form>
  <a class="btn btn-default" href="{{ url_for('top') }}">
    <span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span> 戻る
  </a>
  <form class="text-right" action="{{ url_for('del_user', user_id=target_user.id) }}" method="post">
    <button type="submit" class="btn btn-danger">
      <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> 削除
    </button>
  </form>
{% endblock %}

両ファイルとも、

  • {% extends 'layout.html' %} で共通部分を継承する
  • {% block content %}{% endblock %} の中にコンテンツを書く

CSS ファイル削除

static/style.css ファイルは不要になったので削除します。

表示確認

ブラウザから http://127.0.0.1:5000/ にアクセスすると・・・、

f:id:kaorr_mob:20171218212223p:plain

それなりに良い感じになりましたね。

次に、user ユーザの 詳細 をクリックすると・・・、

f:id:kaorr_mob:20171218212329p:plain

こちらも、それなりに良い感じになりましたね。

おわりに

今回は、Bootstrap を使って見た目をそれなりにしてみました。

次回は本編に戻って、機能追加を行いたいと思います!