flaskによるWebアプリ開発④~SQLAlchemyを使ってデータベースと連動させる

flaskでのWebアプリ開発シリーズ記事一覧

flaskによるWebアプリ開発①~簡単なWebページを表示させてみる

flaskによるWebアプリ開発②~テンプレートエンジン(Jinja2)を使って動的Webページを作る

flaskによるWebアプリ開発③~GETとPOSTとformタグでのデータの送受信

Pythonとデータベースの連携

SQLAlchemy

sqlite

この2つがPythonでデータベースを操作する際に使う代表的なライブラリです。違いとしてはsqliteは用意された関数の中に引数として、そのままデータベースの構文を打ち込むのに対してSQLAlchemyはSQL構文をそのまま書かずに独特の書き方をする点です。

なのでSQLAlchemyだと、データベース側にどういうコードが送られているのかが、慣れないうちはブラックボックスになってしまいます。個人的にはSQLAlchemyの方が使ってしっくりくるの好きですが、この編は人によると思います。

SQLAlchemyとは?

pythonのORMモジュール。SQL操作ができる。

<メリット>

・SQLインジェクション対策がサポートされる。
・クラスなので、SQLをオブジェクト指向で書ける。
・引数に変数を入れるため、文字列の結合などが必要ないので短く書ける。

<注意点>
・ちょっとしたSQLを実行する場合は、ORMを使わない方がコード量が短い。
・英語の文献が多いので学習コストが必要。
・慣れないうちはブラックボックスのコード。

セキュリティの面から考えると、SQLAlchemyの内部コードは読む必要あり。どういうSQLが吐き出されてるかチェックすべき。コメントで、どういうSQLが吐き出されてるか書いておくといいと思う。sqlite3と違って直接SQL文を書かないので、内部で気づかないうちに超重いSQLを叩かれてたりする。

#sqlalchemyのインストール
pip install flask-sqlalchemy

SQLAlchemy使い方

  • db.を紐づけする
  • db.Modelを継承してモデルをつくる
  • db.Columnでcolumnを定義する
  • db.relationshipでモデル同士を繋ぐ

SQLALCHEMY側からデータテーブルを作る

ファイルを実際に作成して説明します。

from flask import Flask, request, render_template
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
SQLALCHEMY_TRACK_MODIFICATIONS = False
app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’] = False
#SQLAlchemyでデータベースに接続する
db_uri = ‘sqlite:///test.db’
app.config[‘SQLALCHEMY_DATABASE_URI’] = db_uri
db = SQLAlchemy(app)
#データベースの仕様をクラスで定義する
class order_table(db.Model):
orderid = db.Column(db.Integer, primary_key=True, autoincrement=True)
pub_date = db.Column(db.DateTime, nullable=False,default=datetime.utcnow)
goods_number = db.Column(db.Integer)
payment = db.Column(db.Text())
def __init__(self, pub_date, goods_number, payment):
self.pub_date = pub_date
self.goods_number = goods_number
self.payment = payment
db.create_all()
 print(‘ok’)

ここではorder_tableというデータテーブルをクラス定義して作成します。今回作るテーブルの要素はorder_id、pub_date goods_number ,payment の4つです。

SQLAlchemyの構文は特殊でコントクラスタ(__init__)の前にデータテーブルの要素の設定(プライマリキーやデータ型)を指定します。

そのあとに初期化メソッド(__init__)でインスタンスを作成した場合にデータを格納するクラス変数を指定しておきます。

そして、このコードを実行すると、ディレクトリ上にtest.dbというファイルが作成されていると思います。

.dbファイルの中身を見る方法

.dbファイルはtxtやhtmlとは違って、PCにデフォルトで搭載されているソフトでは基本的にみることはできません。

なので、扱いにくいファイル形式です。そのため.dbファイルに苦手意識を持つ人が多いです。ですが、データベースはエンジニアであれば避けては通れないものなので、使っていって慣れていくしかありません。

.dbファイルを見る方法は大きく2つあります。

・コマンドラインからsqlite3コマンドを使って開く

・「DB Browser for SQLite」などの可視化ソフトを使用する

現場によってはGUIがない可能性があるので、理想はコマンドラインから開けるようになることですが、コマンドラインからみると味気ないので、可視化ツールが使える環境であれば可視化ツールを使う方が見やすいです。今回はとりあえずコマンドから開いてみます。

cdでFlaskのプロジェクトのディレクトリに移動してsqliteコマンドでdbファイルを開いてみます。sqlite>となれば成功です。

#コマンドラインからdbファイルを開く
$sqlite3 test.db

ファイルが開けたら次はテーブルを確認します。

#dbファイルにあるテーブルの一覧を表示する
.tables

ここにorder_tableとあれば成功です。

SQLAlchemyからテーブルにデータを追加(INSERT文)

次はSQLAlchemyからテーブルにデータを追加します、

<add.py>

from flask import Flask, request, render_template
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
SQLALCHEMY_TRACK_MODIFICATIONS = False
app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’] = False
#SQLAlchemyでデータベースに接続する
db_uri = ‘sqlite:///test.db’
app.config[‘SQLALCHEMY_DATABASE_URI’] = db_uri
db = SQLAlchemy(app)
#テーブルの中身をクラスとして定義する
class order_table(db.Model):
orderid = db.Column(db.Integer, primary_key=True, autoincrement=True)
pub_date = db.Column(db.DateTime, nullable=False,default=datetime.utcnow)
goods_number = db.Column(db.Integer)
payment = db.Column(db.Text())
def __init__(self, pub_date, goods_number, payment):
self.pub_date = pub_date
self.goods_number = goods_number
self.payment = payment
#テーブルに追加するデータ
date=datetime.now()
goods_number=810
payment=‘cash’
#テーブルにデータを追加する
add_data = order_table(date,goods_number,payment)
db.session.add(add_data)
#テーブルへの変更を保存する
db.session.commit()

実行したらデータが追加できているかコマンドラインからdbファイルを開いて確認します。

#テーブルにデータが追加されているか確認する

$sqlite3 test.db
$sqlite> .tables
※order_table

&sqlite> select * from order_table;
※1|2019-05-22 09:51:02.112116|810|cash

それっぽいデータベースにするために、あと2つほど適当にデータを追加します。

#テーブルに追加するデータ
date=datetime.now()
goods_number=811
payment=‘credit’
date2=datetime.now()
goods_number2=812
payment2=‘credit’
#テーブルにデータを追加する
add_data = order_table(date,goods_number,payment)
add_data2 = order_table(date2,goods_number2,payment2)
db.session.add(add_data)
db.session.add(add_data2)
#テーブルへの変更を保存する
db.session.commit()

sqlite> select * from order_table;
1|2019-05-22 09:51:02.112116|810|cash
2|2019-05-22 10:24:00.764144|811|credit
3|2019-05-22 10:24:00.764144|812|credit

テーブルのデータを読み込む(SELECT文)

テーブルにデータが追加できたら次はSELECT文で、SQLAlchemyからテーブルに格納されているデータを読み込んでみます。

SQLAlchemyではテーブルに格納されているデータは.query.all()で呼び出すことができます。試しにさきほど作ったorder_tableの中身を呼び出してみます。

#テーブルのデータを読み込む
order=order_table.query.all()
#読み込んだテーブルのデータをPythonで表示する方法のあれこれ
print(order,type(order))
print(dir(order[0]))
print(order[0].pub_date,order[0].goods_number,order[0].payment)
#for文でテーブルの要素を取得してリストに格納する
goodsdata=[]
for i in order:
goodsdata.append(i.goods_number)
#リストの中身を表示する
print(goodsdata)

order = order_table.query.all() の部分でorderという変数の中にデータテーブルに格納されているデータが渡されました。orderの中身はリストになっており、リストの要素一つあたりに一列ごとにデータがオブジェクト化されて格納されています。↓

[<order_table 1>, <order_table 2>, <order_table 3>] <class ‘list’>

データテーブルの中身を見るためにはリストから1つずつ要素を取り出して.クラス変数名で呼び出してあげるといいです。そのオブジェクトが持つ変数・関数はdir()で確認できます。

[‘__class__’, ‘__delattr__’, ‘__dict__’, ‘__dir__’, ‘__doc__’, ‘__eq__’, ‘__format__’, ‘__ge__’, ‘__getattribute__’, ‘__gt__’, ‘__hash__’, ‘__init__’, ‘__init_subclass__’, ‘__le__’, ‘__lt__’, ‘__mapper__’, ‘__module__’, ‘__ne__’, ‘__new__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__setattr__’, ‘__sizeof__’, ‘__str__’, ‘__subclasshook__’, ‘__table__’, ‘__tablename__’, ‘__weakref__’, ‘_decl_class_registry’, ‘_sa_class_manager’, ‘_sa_instance_state’, ‘goods_number’, ‘metadata’, ‘orderid’, ‘payment’, ‘pub_date’, ‘query’, ‘query_class’]

その中でテーブルに格納している値を持っているのはクラス定義の部分で指定した「pub_date」と「goods_number」と「payment」ですので、これをそれぞれorder[0]の後ろに着けて呼び出すとテーブル1列目の各要素が呼び出せます。

print(order[0].pub_date,order[0].goods_number,order[0].payment)

2019-05-22 09:51:02.112116 810 cash

これがorder[1]order[2]にも同じように格納されているのでfor文で呼び出すことができます。

for i in order:
goodsdata.append(i.goods_number)
print(goodsdata)

[810, 811, 812]

テーブルから特定の要素を抽出する(WHERE文)

次はWHERE文をやってみます。SqlalchemyではWhere文は以下のように記述します。テーブルの列がそのまま呼び出されるので.を付けて中身を呼び出します。

order = order_table.query.filter_by(goods_number=811).first()
print(order)
print(order.orderid,order.goods_number,order.pub_date)

<order_table 2>
2 811 2019-05-22 10:24:00.764144

 テーブルの中身を置換する(UPDATE文)

SQLでいうところのUPDATE文にあたるテーブルのデータ更新は、呼び出したテーブルの要素の中身を変更して保存するだけです。

#テーブルからgoods_numberが811のものを抽出する

order = order_table.query.filter_by(goods_number=811).first()

#goods_numberを850に書き換える
order.goods_number=850
#変更内容を保存
db.session.commit()
#変更結果を確認する
print(order.orderid,order.goods_number,order.pub_date)

<実行結果>

2 850 2019-05-22 10:24:00.764144

このように811が850に書き換えられています。

テーブルから特定の条件のものを削除する

SQLでテーブルの要素の削除にあたるDelete文はdb.session.dalete()で行えます。

#goods_numberが810のものをテーブルから削除する
order = order_table.query.filter_by(goods_number=810).first()
db.session.delete(order)
#変更内容を保存する
db.session.commit()

sqlite> select * from order_table;
2|2019-05-22 10:24:00.764144|850|credit
3|2019-05-22 10:24:00.764144|812|credit

最初のgoods_numberが810の行が削除されているのが分かります。

終わり

以上がPythonのFlaskにおけるSQLAlchemyの基本的な使い方です。Pythonでデータベースを扱うパターンとしては、スクレイピングしたデータを保管する、Flask・Djangoで作ったアプリケーショで扱うデータを管理するという2つが頻度が高い用途だと思います。

プログラミングの独学はとても難しい


プログラミングは小学校の義務教育にも導入され始めており、これから社会人として生きていく上でプログラミングはもはや出来て当たり前、出来なれば論外というエクセルレベルの必須スキルになりつつあります。そしてそういう話を聞いて参考書なりを購入して独学でプログラミング勉強しようと思っている人も少なくないでしょう。しかしプログラミングを独学で勉強し始めようと思うものの



・「分からない箇所で詰まって挫折してしまった」

・「勉強する時間が足りない」

・「ネットの記事だと情報が断片的でよくわからない」

・「コードのエラーの原因が分からない」



という壁にぶち当たって、プログラミングの勉強を止めてしまう方が少なくありません。独学でプログラミングを勉強してる時間のほとんどはつまづいている時間です。実際僕も最初のころ独学でプログラミングを勉強していた頃はエラーの原因が分からず丸1日を不意にしてしまった・・・そんな苦い経験がありました。



それで僕は一度はプログラミングの学習を諦めてしまいましたが、就活で現実を知る中で「プログラミングを勉強して、いずれフリーランスとして自由な生き方がしたい」「エンジニアとして若いうちから高収入を得たい」という気持ちから一念発起して「侍エンジニアのwebサービスコース」に申し込み、プロのエンジニアの方に対面でマンツーマンでPythonによるWebサービス作り方とWeb技術の基本を教えてもらい、ようやくプログラミングが理解でき、今ではエンジニアとしてそこそこの暮らしができるようになりました。





侍エンジニアでは、とりあえずプログラミングやインターネットの基本を知っておきたい人から、HTML・cssなどでWebサイトやWebアプリを作ってみたい人やPythonを勉強してデータサイエンティストやAIエンジニアになりたい人まで幅広いニーズに応えた様々なコースが用意されています。



IT業界と言ってもエンジニアの仕事はプログラミング言語次第でサーバーから機械学習・ディープラーニングまで多種多様ですし、侍エンジニアの無料レッスン(カウンセリング)を受けてみて、自分のやりたいITの仕事は何なのか?を見つけるのがエンジニアへの第一歩になります。ちなみに今侍エンジニアの無料レッスンを受けると1000円分のAmazonギフト券がもらえるので、試しに受けてみるだけもお得です。


自分は半端に独学やオンラインスクールで勉強して金と時間を無駄にするくらいなら、リアルのプログラミングスクールに通ってしっかりプログラミングを勉強した方がいいと思います。ちなみに今、侍エンジニアに申し込むと、25歳以下の学生の方であれば、受講料が20%OFFになるので超お得です。


そして、プログラミングは大勢で授業を受けたり漫然とオンライン学習をするよりも自分が分からない箇所をピンポイントでプロの講師に直接質問して、ちゃんと納得するというスタイルの方がお金は確かに少し掛かりますが、独学で学ぶよりも絶対にモノになります。


シェアする

  • このエントリーをはてなブックマークに追加

フォローする