panco’s blog

興味が沸いたことを書く

SQLite で躓いたこと(sqlite3.OperationalError: no such table)

またまた備忘録。

やりたいこと

作成済みのテーブルから任意のレコードを取得し、ブラウザで画面表示させること。
見た目がダサすぎるのはさておき。

ディレクトリ構成

C:.
│  pog.db
│  test.py
│
│
└─templates
        test.html

sqlite3.OperationalError: no such table: pog_lists

エラー画面

以下のコードを実行したところ、pog_lists などというテーブルはないと怒られた。pog.db に pog_lists テーブルは作成済みであり、SQL 単体で実行すると正常に取得できた。

実行したコード(NG)

test.py

from  flask import Flask, render_template, g
import sqlite3
DATABASE='pog.db'

app = Flask(__name__)

# database 接続
def connect_db():
    rv = sqlite3.connect(DATABASE)
    rv.row_factory = sqlite3.Row
    return rv

# database 取得
def get_db():
    if not hasattr(g,'sqlite_db'):
        g.sqlite_db = connect_db()
    return g.sqlite_db

@app.route('/')
def top():
    pog_lists = get_db().execute('select * from pog_lists where pog_id = 100').fetchall()
    return render_template ('test.html', pog_lists=pog_lists)

if __name__ == "__main__":
    app.run(debug=True)
    # app.run()

test.html

<!-- pog_lists から取得した結果を表示する -->
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>pog_lists</title>
  </head>
  <body>
    <h2>test pog_lists</h2>
    <table border="1">
      <tr>
        <th>pog_id</th>
        <th>dam_year</th>
        <th>horse_name</th>
        <th>gender</th>
        <th>coat_color</th>
        <th>url</th>
        <th>sire</th>
        <th>dam</th>
        <th>maternal_grandfather</th>
        <th>breeder</th>
      </tr>

      <!-- pog_lists は test.py で定義している pog_lists -->
      {% for pog in pog_lists %}
      <tr>
        <td>{{pog.pog_id}}</td>
        <td>{{pog.dam_year}}</td>
        <td>{{pog.horse_name}}</td>
        <td>{{pog.gender}}</td>
        <td>{{pog.coat_color}}</td>
        <td>{{pog.url}}</td>
        <td>{{pog.sire}}</td>
        <td>{{pog.dam}}</td>
        <td>{{pog.maternal_grandfather}}</td>
        <td>{{pog.breeder}}</td>
      </tr>
    {% endfor %}
    </table>
  </body>
</html>

エラー原因

本来参照してほしい DB が参照されていないことが原因だった。
画面表示した際、作成したものとは別の pog.db が作成されていた。sqlite3.connect() で対象の DB が存在しない場合、新たに DB を作成する。そのため、新たに作成された 0 KB の pog.db を参照して pog_lists テーブルは存在しないと言っていたということだった。

対処

  • test.py の DATABASE の設定値を修正した
  • test.py と pog.db は同じ階層にあるため、'pog.db' と設定すればよいと思っていたが、動き的にはそうではなかった

修正後の test.py

from  flask import Flask, render_template, g
import sqlite3
DATABASE='pog-draft-project/pog.db'

app = Flask(__name__)

# database 接続
def connect_db():
    rv = sqlite3.connect(DATABASE)
    rv.row_factory = sqlite3.Row
    return rv

# database 取得
def get_db():
    if not hasattr(g,'sqlite_db'):
        g.sqlite_db = connect_db()
    return g.sqlite_db

@app.route('/')
def top():
    pog_lists = get_db().execute('select * from pog_lists where pog_id = 100').fetchall()
    return render_template ('test.html', pog_lists=pog_lists)

if __name__ == "__main__":
    app.run(debug=True)
    # app.run()