1.3. クラス
DALを使うには構成するクラスを知る必要があります。これらのクラスについて説明します。
1.3.1. 主要なクラス
DALには非常に多くのクラスが含まれます。この中にはフレームワークを利用する上で、どうしても知っている必要があるクラスがあります。このようなクラスを次に挙げてみます。
| クラス |
説明 |
詳細説明 |
| DAL |
データベースに関するクラス |
DAL |
| Field |
フィールドに関するクラス |
Field |
| Table |
テーブルに関するクラス |
Table |
| Query |
条件式に関するクラス |
Query |
| Expression |
式に関するクラス |
Expression |
| Set |
レコードセット定義に関するクラス |
Set |
| Rows |
レコードセットに関するクラス |
Rows |
| Row |
レコードに関するクラス |
Row |
これらのクラスとその主な機能(メソッド)を表したのが次の図になります。
DALクラス — データベースに関するクラス
|
コンストラクタ
| データベース接続 |
define_table()
| テーブル定義 |
commit() / rollback()
| トランザクション制御 |
executesql()
| 直接SQL文を実行 |
export_to_csv_file()
| 全テーブルのCSVエクスポート |
import_from_csv_file()
| 複数テーブルのCSVインポート |
tables()
| テーブル一覧 |
smart_query()
| スマートクエリ |
Fieldクラス — フィールドに関するクラス
|
コンストラクタ
| フィールド定義
|
count()
| フィールドのカウント
|
formatter()
| フィールドのバリデータ表示フォーマット値
|
validate()
| フィールドのバリデータ
|
Tableクラス — テーブルに関するクラス
|
insert()
| レコードの追加 |
bulk_insert()
| レコードをまとめて追加 |
update_or_insert()
| レコード更新or追加 |
validate_and_insert()
| バリデータとレコード追加 |
truncate()
| 全レコードの削除 |
drop()
| テーブルの削除 |
import_from_csv_file()
| CSVファイルからのインポート |
with_alias()
| テーブル別名設定 |
fields()
| テーブルのフィールド一覧 |
_insert()
| SQL文生成 |
_drop()
| SQL文生成 |
_truncate()
| SQL文生成 |
_enable_record_versioning()
| レコードバージョン管理 |
— ショットカット機能(リスト型エミュレーション) —
|
| myrecord = db.mytable[id] | レコードの取得 |
| db.mytable[0] = dict(myfield='value') | レコードの追加 |
| db.mytable[id] =dict(myfield='value') | レコードの更新 |
| del db.mytable[id] | レコードの削除 |
— ショットカット機能(関数エミュレーション) —
|
| row = db.mytable(id) | レコードの取得(ID指定) |
| row = db.mytable(db.mytable.id==id) | レコードの取得(Query指定) |
| row = db.mytable(myfield='value') | レコードの取得(パラメータ指定) |
| row = db.mytable(id,myfield='value') | レコードの取得(id,辞書型) |
|
Queryクラス — 条件式に関するクラス
|
case()
| SQLのCASE式による置換
|
as_dict()
| クエリ式を辞書値に変換
|
as_json()
| クエリ式をjsonに変換
|
as_xml()
| クエリ式をxmlに変換
|
Expressionクラス — 式に関するクラス
|
— 条件式 —
|
like()
| あいまい検索 |
startswith()
| 前方一致検索 |
endswith()
| 後方一致検索 |
contains()
| 部分一致検索 |
belongs()
| IN演算子 |
regexp()
| 正規表現による検索 |
— データ操作 —
|
sum()
| 合計値計算 |
avg()
| 平均値計算 |
max()
| 最大値の取得 |
min()
| 最小値の取得 |
len()
| 長さの取得 |
abs()
| 絶対値取得 |
coalesce()
| NULL値の変換 |
coalesce_zero()
| NULL値のゼロ変換 |
upper()
| 大文字変換 |
lower()
| 小文字変換 |
year()
| 日付時間の要素抜き出し |
month()
|
day()
|
hour()
|
minutes()
|
seconds()
|
|
Setクラス — レコードセット定義に関するクラス
|
select()
| レコードセット取得 |
count()
| レコード件数取得 |
isempty()
| レコード存在チェック |
update()
| レコードの更新 |
update_naive()
| レコードの更新 (コールバック関数の無視) |
validate_and_update()
| バリデータとレコード更新 |
delete()
| レコードの削除 |
nested_select()
| ネストしたSELECT |
_select()
| SQL文生成 |
_count()
| SQL文生成 |
_update()
| SQL文生成 |
_delete()
| SQL文生成 |
Rowsクラス — レコードセットに関するクラス
|
first()
| 最初のレコードを取得 |
last()
| 最後のレコードを取得 |
as_dict()
| 辞書型に変換 |
as_list()
| リスト型に変換 |
as_trees()
| 木構造のデータをリスト型に変換 |
find()
| レコードセット内検索 |
exclude()
| レコードセットの切り抜き |
sort()
| レコードセットのソート |
setvirtualfields()
| 仮想フィールドの設定 |
export_to_csv_file()
| CSVファイルへのエクスポート |
xml()
| xml/htmlに変換 |
json()
| jsonに変換 |
Rowクラス — レコードに関するクラス
|
as_dict()
| 辞書型に変換 |
— 組み込み関数 —
|
update_record()
| Rowと共にDB上のレコードも更新 |
delete_record()
| Rowと共にDB上のレコードも削除 |
|
クラスとそのクラスに属する機能(メソッド)を知るのは、DALを使いこなす上で重要な事項になります。
1.3.2. DAL構文とクラスの関係
次にDAL構文とクラスの関係について、サンプルコードを使って示してみます。
データベース接続
サンプルコード
>>> db = DAL('sqlite://storage.db')
サンプルとクラスの関連図
テーブル定義
サンプルコード
>>> db.define_table('person',
... Field('name'), format='%(name)s')
サンプルとクラスの関連図
レコード検索と出力
サンプルコード
>>> rows = db(db.person.id > 0).select()
>>> for row in rows:
... print row.name
...
Potamata
Cotasata
Tamodama
サンプルとクラスの関連図
クラスをコード断片毎に、詳細に見ていきます。
| コード |
クラス |
| db |
DAL |
| db.person |
Table |
| db.person.id |
Field |
| db.person.id > 0 |
Query |
| db() |
DAL |
| db(db.person.id > 0) |
Set |
| rows = db(db.person.id > 0).select() |
Rows |
| row = rows[0] |
Row |
| row.name |
文字列 |
DAL構文とクラスは密接に関係しているということが、理解できるのではないでしょうか。
1.3.3. DALとTable、Fieldクラスについて
DALはデータ接続、Tableはテーブル、Fieldはフィールドに関するクラスですが、これらは交互に互いのクラスにアクセス可能になっています。
DALクラスの属性としてTableクラスが、Tableクラスの属性としてFieldクラスへのアクセスができます。
| コード |
クラス |
| db |
DAL |
| db.person |
Table |
| db.person.id |
Field |
DALとTableクラスの基底クラスは、dict(辞書)クラスです。このため次のように辞書型として各クラスにアクセス可能です、
| コード |
クラス |
| db |
DAL |
| db[‘person’] |
Table |
| db.person.[‘id’] |
Field |
| db[‘person’][‘id’] |
Field |
親となる接続やテーブルに、クラスを逆に遡ることも可能です。
| Fieldクラス |
| コード |
クラス |
| db.person.id |
Field |
| db.person.id._table |
Table |
| db.person.id._db |
DAL |
| Tableクラス |
| コード |
クラス |
| db.person |
Table |
| db.person._db |
DAL |
これらは属性として管理されています。
また次のように、接続やテーブルの名前を文字列として参照可能な属性もあります。
| コード |
文字列 |
| db.person.id._tablename |
‘person’ |
| db.person._tablename |
‘person’ |
| db.person._db |
‘sqlite’ |
| db._uri |
‘sqlite://storage.sqlite’ |
また、DALクラスやTableクラスのオブジェクトはイテレータとして、TableオブジェクトやFieldオブジェクトを取り出すことが可能です。
>>> for t in db:
... print t
...
auth_user
auth_group
auth_membership
auth_permission
auth_event
auth_cas
person
>>> for f in db.person:
... print f
...
person.id
person.name
詳細は、 DAL , Table , Field を参照ください。
1.3.4. QueryとExpression クラスについて
QueryとExpressionと2つのクラスがありますが、Queryは条件式、Expressionは式に関するクラスです。
具体的に示してみます。
Queryクラス
>>> qry = db.person.name == 'Potamata' # personのnameが'Potamata'とイコールという条件式
>>> type(qry)
<class 'gluon.dal.Query'>
qryはQueryインスタンスになります。
Expressionクラス
>>> exp = db.item.unit_cost * 1.1 # コスト単価を1.1倍にする式
>>> type(exp)
<class 'gluon.dal.Expression'>
expはExpressionインスタンスです。
これらのインスタンスは、他のクラスのメソッドなどの引数として使用することになります。
またExpressionクラスは、Queryクラスを返すメソッドを幾つか持っています。
サンプルコード
>>> qry = db.person.name.like('P%')
>>> type(qry)
<class 'gluon.dal.Query'>
db.person.nameはFieldクラスですが、FieldクラスはExpressionクラスを継承しています。このためExpressionクラスのメッソド like の呼び出しが可能です。likeメソッドは、あいまい検索のQueryインスタンスを返します。
詳細は、 Query , Expression を参照ください。
1.3.5. Set Rows Row クラスについて
Set Rows Row の各クラスは具体的に、どんなクラスなのでしょうか。この3つのクラスを説明したのが次の図です。
Setはレコードセットを定義していますが、データの実体としては何もありません。Rowsインスタンスが生成された時点で、初めてクエリを実行します。そして、データベースからデータが取り出されてメモリ上に格納します。
Rowsはメモリ上にあるレコードの塊と考えればよいです。
RowはRowsをさらに分解して、一レコード単位にしたものです。
RowsとRowのインスタンスは、既にデータベースから切り離されています。このためRows及びRowインスタンスのデータを改変しても、データベース上のデータには影響しません。
Rowsはイテレータを使用し、Rowを取り出すことができます。
サンプルコード
>>> rows = db(db.person.id > 0).select()
>>> for row in rows:
... print row.name
...
Potamata
Cotasata
Tamodama
また基底クラスが、dict(辞書)クラスではありませんが、RowsやRowは辞書型をエミュレートします。
| Rowsクラス |
| コード |
クラス |
| rows = db(db.person.id > 0).select() |
Rows |
| row = rows[0] |
Row |
| rows[0][‘name’] |
文字列 |
| Rowクラス |
| コード |
クラス |
| row.name |
文字列 |
| row[‘name’] |
文字列 |
| row(person.name) |
文字列 |
詳細は、 Set , Rows , Row を参照ください。