シェルスクリプトマガジン

Pythonあれこれ(Vol.78掲載)

著者:飯尾 淳

本連載では「Pythonを昔から使っているものの、それほど使いこなしてはいない」という筆者が、いろいろな日常業務をPythonで処理することで、立派な「蛇使い」に育つことを目指します。その過程を温
かく見守ってください。皆さんと共に勉強していきましょう。第8回は、Webアプリケーションフレームワーク「Flask」を使って基本的なWebアプリを作成する方法を紹介します。データベースにアクセスする方法やテンプレートの利用方法も解説します。

シェルスクリプトマガジン Vol.78は以下のリンク先でご購入できます。

図1 「Hello World」に相当するシンプルなWebアプリのコード(app.py)

from flask import Flask

app = Flask(__name__)
@app.route('/')
def hello():
  return '<h1>Hello World!</h1>'

図4 ルーティングの記述を追加したWebアプリのコード

from flask import Flask
app = Flask(__name__)

@app.route('/hello')
def hello():
  return '<h1>Hello World!</h1>'

@app.route('/goodbye')
def goodbye():
  return '<h1>Good-bye World!</h1>'

図5 パスパラメータを使うWebアプリのコードの例

from flask import Flask
app = Flask(__name__)

@app.route('/hello/<name>')
def hello(name):
  return f'<h1>Hello {name}!</h1>'

図7 クエリーパラメータを使うWebアプリのコードの例

from flask import Flask, request
app = Flask(__name__)

@app.route('/hello')
def hello():
  name = request.args['name']
  return f'<h1>Hello {name}!</h1>'

図9 メモ帳Webアプリのひな型コード

from flask import Flask, request
app = Flask(__name__)

@app.route('/addMemo')
def addMemo():
  name = request.args['name']
  description = request.args['description']
  return f'ADD: name = {name}, desc = {description}'

@app.route('/getMemo')
def getMemo():
  return f'[TBD]'

図10 データベースを使うメモ帳Webアプリのコード(その1)

from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Integer, String, Text

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

db = SQLAlchemy(app)

class Memo(db.Model):
  __tablename__ = 'memo'
  ID          = db.Column(Integer, primary_key=True)
  NAME        = db.Column(String(500))
  DESCRIPTION = db.Column(Text)

db.create_all()

@app.route('/addMemo')
def addMemo():
  name = request.args['name']
  description = request.args['description']
  return f'ADD: name = {name}, desc = {description}'

@app.route('/getMemo')
def getMemo():
  return f'[TBD]'

図12 データベースを使うメモ帳Webアプリのコード(その2)

from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Integer, String, Text

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

db = SQLAlchemy(app)

class Memo(db.Model):
  __tablename__ = 'memo'
  ID          = db.Column(Integer, primary_key=True)
  NAME        = db.Column(String(500))
  DESCRIPTION = db.Column(Text)

db.create_all()

@app.route('/addMemo')
def addMemo():
  name = request.args['name']
  description = request.args['description']
  db.session.add(Memo(NAME=name, DESCRIPTION=description))
  db.session.commit()
  db.session.close()
  return f'ADD: name = {name}, desc = {description}'

@app.route('/getMemo')
def getMemo():
  memos = db.session.query(
    Memo.ID, Memo.NAME, Memo.DESCRIPTION).all()
  return str(memos)

図14 テンプレートファイル「index.html」の内容

<!DOCTYPE html>
<html>
  <head>
    <title>Flask Test</title>
  </head>
  <body>
    <h1>The Memo List</h1>
    <table>
      <tr><th>ID</th><th>Name</th><th>Description</th></tr>
      {% for memo in memos: %}
      <tr><td>{{ memo.0 }}</td>
          <td>{{ memo.1 }}</td>
          <td>{{ memo.2 }}</td></tr>
      {% endfor %}
    </table>
  </body>
</html>

図15 テンプレートを使うメモ帳Webアプリのコード(その1)

from flask import Flask, request, render_template
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Integer, String, Text

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

db = SQLAlchemy(app)

class Memo(db.Model):
  __tablename__ = 'memo'
  ID          = db.Column(Integer, primary_key=True)
  NAME        = db.Column(String(500))
  DESCRIPTION = db.Column(Text)

db.create_all()

@app.route('/addMemo')
def addMemo():
  name = request.args['name']
  description = request.args['description']
  db.session.add(Memo(NAME=name, DESCRIPTION=description))
  db.session.commit()
  db.session.close()
  return f'ADD: name = {name}, desc = {description}'

@app.route('/getMemo')
def getMemo():
  memos = db.session.query(
    Memo.ID, Memo.NAME, Memo.DESCRIPTION).all()
  return render_template('index.html', memos=memos)

図17 修正したテンプレートファイル「index.html」の内容

<!DOCTYPE html>
<html>
  <head>
    <title>Flask Test</title>
  </head>
  <body>
    <h1>The Memo List</h1>
    <table border="1" width="500" cellspacing="0"
           cellpadding="5" bordercolor="#333333">
      <tr><th>ID</th><th>Name</th><th>Description</th></tr>
      {% for memo in memos: %}
      <tr><td>{{ memo.0 }}</td>
          <td>{{ memo.1 }}</td>
          <td>{{ memo.2 }}</td></tr>
      {% endfor %}
    </table>
    <h2>New Memo</h2>
    <form action="/addMemo" method="post">
      <table style="text-align: left;">
        <tr style="vertical-align: top;"><th>Name:</th>
          <td><input type="text" name="name"></input></td></tr>
        <tr style="vertical-align: top;"><th>Description:</th>
          <td><textarea name="description" rows="4" cols="40">
              </textarea></td></td>
      </table>
      <input type="submit" value="Submit">
      <input type="reset" value="Reset">
    </form>
  </body>
</html>

図18 テンプレートを使うメモ帳Webアプリのコード(その2)

from flask import Flask, request, render_template, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Integer, String, Text

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

db = SQLAlchemy(app)

class Memo(db.Model):
  __tablename__ = 'memo'
  ID          = db.Column(Integer, primary_key=True)
  NAME        = db.Column(String(500))
  DESCRIPTION = db.Column(Text)

db.create_all()

@app.route('/addMemo', methods=['POST'])
def addMemo():
  name = request.form['name']
  description = request.form['description']
  db.session.add(Memo(NAME=name, DESCRIPTION=description))
  db.session.commit()
  db.session.close()
  return redirect(url_for('getMemo'))

@app.route('/getMemo')
def getMemo():
  memos = db.session.query(
    Memo.ID, Memo.NAME, Memo.DESCRIPTION).all()
  return render_template('index.html', memos=memos)