よく使うFlaskの基本構成とajax通信、SQLite3接続法

#概要
Flaskというwebアプリケーションフレームワークを使うにあたって私がよく使う構成とDB接続方法などをまとめてみました。
流れとしては最初に構成の説明をしたあとに、ボタンをクリックするたびにDBからランダムにデータを取得して画面に出力するという簡単なアプリを作成していこうと思います。

#この記事の対象
+ Webアプリを簡単に実装してみたいかた（入門者）
+ pythonを用いてのwebアプリ作成に興味があるかた
+ FlaskでAjax通信やDB接続などをしてみたいかた

#今回使用するもの
Flask
SQLite3
Ajax

#使用するものの説明
##Flask
Pythonのwebアプリケーションフレームワークで有名なDjangoに比べてかなり軽量。
>Flask（フラスク）は、プログラミング言語Python用の、軽量なウェブアプリケーションフレームワークである。標準で提供する機能を最小限に保っているため、自身を「マイクロフレームワーク」と呼んでいる。
[引用元](https://ja.wikipedia.org/wiki/Flask)

##SQLite3
データベースをファイルとして保存するもの。
今回は簡単な実装を目指すためこちらを使用します。
>サーバとしてではなくアプリケーションに組み込んで利用されるデータベースである。 一般的なRDBMSと違い、APIは単純にライブラリを呼び出すだけであり、データの保存に単一のファイルのみを使用することが特徴である。
[引用元](https://ja.wikipedia.org/wiki/SQLite)

##Ajax
>Ajaxとは、あるWebページを表示した状態のまま、別のページや再読込などを伴わずにWebサーバ側と通信を行い、動的に表示内容を変更する手法。
[引用元](http://e-words.jp/w/Ajax.html)

#環境構築
今回はPython3が実行できることを前提で行っていきます。
もし実行環境がない場合は[こちら](https://bi.biopapyrus.jp/os/win/win-install-python.html)を参照してPython3の構築をお願いいたします。
##Flask
```python
pip install flask
# anacondaを使用している方はこちら
conda install flask
```
基本的にはこちらのコマンドでダウンロードできるのですが、anacondaを使用している場合はpipを用いると環境が壊れる危険性があるようなので注意です。

##SQLite3
[参考サイト](https://www.dbonline.jp/sqlite/install/index1.html)
こちらのサイトを参考にしていただくとスムーズにダウンロードできると思います。

またSQLiteをGUI上で操作するためにこちらをいれておくのもおすすめです。
[DB Browser for SQLite](https://sqlitebrowser.org/)
本記事ではこちらのGUIツールを用います。

#Flaskの基本構成
```bash
flask_base 
├── main.py
├── models
├── static 
│   ├── css
│   │   └── hello.css
│   └── js
│       └── hello.js
└── templates
    ├── hello.html  
    └── layout.html
```
私はこんな形の構造で使用しています。
一応githubに同じ構造をあげているので
`git clone https://github.com/murajo/flask_base.git`
で同じ構造を持ってくることができます。

それではそれぞれのファイルやディレクトリを簡単に説明します。

##main.py
``` python:main.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def hello_view():
  heading_1 = "Hello,World"
  return render_template('hello.html', title='flask now!', heading_1=heading_1)

if __name__ == '__main__':
  app.run()
```
ルーティングを行うためのファイルで、アクセスされたURLに応じてHTMlを返します。
HTMLを返す際にpython側から値を返すことができてHTML側で扱うことができます。
この例だとtitleとheading_1(h1)という変数を返しております。

##models
modelsは「DBから値をとってくる」などの処理を記述したファイルをいれる場所です。
先程解説したmain.pyから呼びだすファイルをまとめます。
今は何も入っておりませんが後ほど作成していきます。

##static
CSSやJSなどのファイルをいれて使用しております。
他にはimagesやsqliteなどのファイルもいれたりして使用します。

##templates
main.pyで返すHTMlを入れるディレクトリです。
中に入っている2つのHTMlの解説もします。

###layout.html
```html:templates/layout.html
<!doctype html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>{{ title }}</title>
    <link rel="stylesheet" href="../static/css/layout.css" type="text/css">
    <script>
    </script>
</head>
<body>
    {% block content %}
    <!-- 呼び出しもとのHTML -->
    {% endblock %}
</body>
</html>
```
こちらのファイルは基本的にヘッダー・フッターのような共通処理を記述するために使用しております。
メインで呼び出されるファイルからこちらを呼び出して使います。
`<!-- 呼び出しもとのHTML -->`というところに呼び出しもとのHTMlが入ります。
今回の場合は呼び出しもとはbody内だけ書けばいいということです。
titleタグにある`{{title}}`という記述はpython側から返した変数を呼んでおります。
今回はやっていないのですが、CSSのパスなども変数を使えば呼び出しもとで指定したりできます。

###hello.html
```html:templates/hello.html
{% extends "layout.html" %}
{% block content %}
  <h1>{{ heading_1 }}</h1>
{% endblock %}

```
メインで呼び出されるHTMLです。
`{% extends "layout.html" %}`の部分でlayout.htmlを呼んでおります。
この例の場合だとbody内の記述があまりないためすごくスッキリしてますね。

##実行
それでは試しにこのまま実行してみましょう。
実行方法はコマンドラインにて`python main.py`とmain.pyが存在するディレクトリで打てば実行できます。
実行すると下記のような出力になると思うので一番下にあるURLにアクセスしてください。

```python
 * Serving Flask app "main" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/38b76926-2a8f-9a2b-9fa6-289aad0a2db2.png)
アクセスしてこんな形でHello,Worldが出ていれば大丈夫です。

#SQLiteとAjaxを用いた簡単なアプリケーション作成
それでは早速アプリケーションの作成をしていこうと思います。
基本的には先程解説で使ったflask_baseをベースに作っていきます。
最初に説明したので繰り返しになりますが、ボタンを押すたびにDBから値を取得してきて表示するだけのものです。
今回は題材として挨拶を用いていこうと思います。
朝、昼、夜それぞれの挨拶とそれに対応した画像を表示していこうと思います。

##DBの作成
最初は呼び出すためのDBを作成します。
DB Browser for SQLiteの画面で説明していきます。
それでは早速DBを作成していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/05f40f95-6242-62f3-5975-994aa86d457b.png)
アプリを起動したら左上にNew Databaseという項目があると思いますのでそちらをクリックしてください。
保存場所が出ると思いますので、今回はflask_baseの中のstatic内に保存していこうと思います。
ファイル名は今回はとりあえずhello.sqliteとしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/3ef4813f-29a0-75c7-2479-4a43f0f350b3.png)
ファイル名を指定して作成するとtabeleを作成するウィンドウが出てくる思いますので上記のように作成をしてください。
今回はgreetingsという挨拶テーブルを作り中にIDと挨拶のテキストをいれるgreetingと画像のパスをいれるimage_pathを作成しておきます。
入力が終わりましたらOKを押してもとの画面に戻ってください。

次はテーブルの中にデータを入れていきます。
今回は入力を省略するためにこちらで用意したSQLを入力して行こうと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/1fd4ce09-1f74-2469-126e-2cb161f7738a.png)
画像で囲んでいるExecute SQLという箇所をクリックして下記にあるSQLを貼り付けて実行してください。

```sql
INSERT INTO greetings (greeting, image_path) VALUES ('Good morning','http://urx3.nu/UBv2');
INSERT INTO greetings (greeting, image_path) VALUES ('Hello','http://urx3.nu/REm4');
INSERT INTO greetings (greeting, image_path) VALUES ('Good evening','http://urx3.nu/xUVy');
```
successfullyみたいな出力がでていれば完了です。
ちなみに画像はイラスト屋さんのものを使用させていただいております。
一応これでDB作成の項目は終わりです。
自分で好きな値を入れてみたいという方はExecute SQLの左側にあるBrowse Tableというところから簡単に入れられるのでお試しを！

##SQLite3接続処理作成
それでは早速先ほど作成したDBから値を取得するための処理を作成していきます。
modelsの中にpythonファイルを作成してそこに記述していきます。
記述内容を下記に出します。

```python:dbtool.py
import sqlite3
import random

db_path = 'static/hello.sqlite3'

import sqlite3
import random

db_path = 'static/hello.sqlite3'

# ランダムでDBからgreetingを一つ取得
def get_random_greeting():
  table = 'greetings'
  id_list = get_id_list(table)
  # id一覧からランダムで一つ選びだす
  random_id = random.choice(id_list)['id']
  sql = 'SELECT greeting,image_path FROM ' + table + ' WHERE id=' + str(random_id)
  greeting = execute_sql(sql)
  # 取得データは一つだけなのでここで0を指定しておく
  return greeting[0]

# DBに接続してsqlを実行
def execute_sql(sql):
  con = sqlite3.connect(db_path)
  con.row_factory = sqlite3.Row
  cur = con.cursor()
  cur.execute(sql)
  result = cur.fetchall()
  con.close()
  return result

# 指定したtableのID一覧を取得
def get_id_list(table):
  sql = 'SELECT id FROM ' + table
  id_list = execute_sql(sql)
  return id_list
```
今回使用するsqliteから値を取得する関数は単純で指定したパスのsqliteファイルに一般的なSQLを投げるだけです。
しかし今回のSQLは非常に単純なものなのでまだわかりやすいですが、条件が複雑になると工夫が必要になってくると思われます。

## ルーティング部分の作成
今度はmain.pyの中のルーティング部分を作成します。
HTML呼び出しの部分はベースとほとんど一緒で使いますが、Ajaxからの通信を受け取る部分を新しく作成していきます。
Jsonでやりとりを行うためimportをお忘れなく！

```python:main.py
from flask import Flask, render_template, json, jsonify
from models import dbtool

app = Flask(__name__)

@app.route('/')
def hello_view():
  return render_template('hello.html', title='random_greeting')

# ランダムに挨拶を取得してjsonとして返す
@app.route('/greeting_post', methods=['POST'])
def greeting_process():
  # 先程作成したdbtool.pyのメソッド呼び出し
  result_greeting = dbtool.get_random_greeting()
  return_json = {
    'greeting': result_greeting['greeting'],
    'image': result_greeting['image_path']
  }
  return jsonify(ResultSet=json.dumps(return_json))

if __name__ == '__main__':
  app.run()
```
hello_viewは少しだけ変更をしてHTMLファイルの指定とtitleタグの指定だけにしました。
Ajaxのところは/greeting_postというURLにアクセスされたときにjsonを返すように作られています。

## HTML側の作成
では表示側を作成していきます。
一応今回はajaxを扱うためlayout.htmlにjqueryを読み込んでおきます。
`<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>`
こちらをheadタグの中に入れておいてあげてください。

ではbody側の作成に入ります。

```html:templates/hello.html
{% extends "layout.html" %}
{% block content %}
  <h1>三種の挨拶</h1>
  <p>ボタンをクリックするたびに三種類の挨拶から一つ出力されるぞ！</p>
  <input type="button" value='挨拶' onclick="post_greeting()">
  <br>
  <p>挨拶：<span id="greeting">上のボタンを押してね</span></p>
  <img id="greeting_image" width="256" height="256" src="http://urx3.nu/Zlxt">
  <script src="../static/js/hello.js"></script>
{% endblock %}
```
絶対必要なのはbutton部分にonclickをつけてあげるのと、JSで書き換える場所に固有のidをつけてあげることです。
それ以外は割と適当でも大丈夫です。
私は画像部分が最初何も無いのが寂しいのでイラスト屋から適当に初期画像をセットしています。

## ajax処理

```js:static/js/hello.js
function post_greeting() {
  $.ajax({
    type: 'POST',
    url: '/greeting_post',
    data: '',
    contentType: 'application/json',
    success: function (data) {
      const greeting = JSON.parse(data.ResultSet).greeting
      const greeting_image = JSON.parse(data.ResultSet).image_path
      document.getElementById('greeting').innerHTML = greeting
      document.getElementById('greeting_image').src = greeting_image
    }
  })
}
```
url部分にmain.pyに作成した通信部分のパスを、data部分は渡す必要が無いので空にしてあります。
取得してきたjsonをparse後getElementByIdを用いてHTMLを動的に書き換えています。

## 完成
一応これで一連のコーディングは終えたため、画面に出力してみたいと思います。
`python main.py`を実行して動作確認をしてみましょう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/38e107c1-c798-3ea2-f0e6-0fd33d7ef9e0.png)
私と全く同じに作っていた場合こんな画面になっていると思われます。
では早速ボタンを押して動的処理ができているか見ていきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/0ac6f773-b85f-f27e-b203-ac04be0f3c86.png)
ここはランダムに出力されるように作成したので人によって結果は違うと思いますが、挨拶と画像が変更されていれば成功です。
あとは押すたびに出力が変わるかも確認してみましょう。

#まとめ
今回は構成の説明から簡単なアプリケーション作成まで行いました。
Ajax通信を用いてDBから値を取得するのもやり方さえわかったしまえば意外と簡単です。
今回のやつで扱った機能でちゃんとしたアプリケーションも作成していけると思います。
Flaskでアプリ作ってみようかなと思っている人のお力になれていることを祈ります。