PythonでTUIアプリを作ろう 第二部入魂編 ( その2 ListDBの構造について )
今回は、アプリケーションの中核となるListDBの構造について説明します。
[1] ListDBの概要
まずは、最初に概念図を示しましょう。
見ていただけばわかりますが、非常に単純な構造となっています。Python側のクラスは、ListDBとListDataの2つのみ。この組み合わせが、一つのデータ(テーブルのようなもの)になっており、ListDBでデータの構成を定義、実際のデータはListDataに入る形態となります。
すなわち、1つのデータは、ListDBとListDataが、1:Nの親子関係で対応します。
(1) フィールド構成
ListDBは、データ構造の定義を格納するクラスです。
dbName データの名称
Field01Name フィールド1の名称
Field02Name フィールド2の名称
CategoryList 分類項目(カンマ区切りで複数指定)
ListDataには、実データが4つのフィールド内に格納されます。
Category 分類項目
Field01 データフィールド1
Field02 データフィールド2
Note 複数行の文字列
(2) データベース構造
Pythonクラスのデータは、RDB(SQLite3)にマッピングされます。ListDBの定義情報は、MetaTableというテーブルに、実データはdbNameに定義された名称のテーブルとして格納されていきます。
(3) 関数
下記の関数で、PythonクラスとRDBがマッピングされる構造です。基本的に処理は、Managerクラスのメソッドで実行されます。
# 1.Managerの獲得と初期化
manager = get_manager(database_name, database_connect)
# database_name : 使用するデータベース 'SQLITE3' 'MYSQL'
# database_connect : データベースの接続文字列
# 2.Managerの終了
manager.close()
# 3.データの初期化。全データが削除されます。
manager.define()
# 4.指定されたCSVファイルからデータをimport。問題なければ、’True'が返る。
ret_code = manager.import_csv(fname)
# fname : CSVファイル名
# 5.登録されているデータの一覧を得る
db_names = manager.get_db_names()
# 6.データ(db_name)に指定されているCategory一覧を配列で得る。
categories = manager.get_category_list(db_name)
# db_name : データ名
# 7.データ(db_name)の検索を実行。ListDBオブジェクトが返される。
listdb = manager.search_db(db_name, category=None, search=None, from_rec=1, count_rec=0)
# db_name : データ名
# category=None : 検索対象のCategory(defaultは、なし)
# search=None : 検索対象の文字列(defaultは、なし)
# from_rec=1 : 開始レコード(default(1)は、最初のレコードから)
# count_rec=0 : 検索する件数(default(0)は、全件対象)
# 8.データ(db_name)のレコード件数を得る。
record_counts =get_record_count(db_name, category=None, search=None)
# db_name : データ名
# category=None : 検索対象のCategory(defaultは、なし)
# search=None : 検索対象の文字列(defaultは、なし)
# 9.データ(db_name)の挿入。追加されたレコード番号が返される。
number = manager.insert(db_name, listdata)
# db_name : データ名
# listdata : ListData
# 10.データ(db_name)の更新。更新後のListDBオブジェクトが返される。
listdb = manager.update(db_name, id, listdata)
# db_name : データ名
# id : 番号
# listdata : ListData
# 11.データ(db_name)の削除。
manager.delete(db_name, id)
# db_name : データ名
# id : 番号
[2] データロード
データは、原則としてCSVから一括追加することを想定しています。
(1) CSVの形式
CSVは、1件目が定義情報、2件目以降が実データになります。
1) 定義情報
データ名,フィールド1の名称,フィールド2の名称,CategoryList
の様に指定します。CategoryListは、カンマ(’,’)で複数設定しておきます。
2) 実データ
Category,Field01,Field02,Note
上記の様に指定します。Note内のカンマ(’,’)は、’改行’に変換されて、複数行データとなります。
以下に、実際のCSVファイルを示します。
ブックオフ店舗情報(東京都),name,address,千代田区,港区,新宿区,文京区,台東区,墨田区,江東区,品川区,目黒区,大田区,世田谷区,渋谷区,中野区,杉並区,豊島区,北区,板橋区,練馬区,足立区,江戸川区,八王子市,立川市,武蔵野市,青梅市,府中市,昭島市,調布市,町田市,小平市,国立市,福生市,東大和市,東久留米市,多摩市,西東京市
千代田区,BOOKOFF 秋葉原駅前店,東京都千代田区神田佐久間町1-6-4 ,03-5207-6206,10:00~21:00
港区,BOOKOFF総合買取窓口 田町駅西口店,東京都港区芝5丁目32-3 1F,03-5439-4131,11:00~20:00
新宿区,BOOKOFF 飯田橋駅東口店,東京都新宿区揚場町1-11 ,03-5206-6831,10:00~21:00
:
:
この例では、
データ名 : ブックオフ店舗情報(東京都)
フィールド1の名称 : name
フィールド2の名称 : address
CategoryList : 千代田区,港区,新宿区,....
として定義しています。
3) 制限事項
データにカンマは使えません。
区切り文字として使用しているからです。タブを使えば良いと思われるかもしれませんが、これには理由があるのです。
ここまで説明してきましたように、わたしはデータをListDB形式で管理しているのですが、手でデータを作ることも少なくありません。
例えば、旅行に行くときには、そこにある古本屋、銭湯、飲食店などなど、気になる情報をWebなどからコピーして、ListDB形式にEditorでまとめて持っていくということやっているのです。
おわかりかと思いますが、TabのようなコードをEditorで扱うのは一苦労、データを壊してしまうこともありがちです。これは精神衛生上よくないので、扱いやすいカンマを区切り文字に固定してしまったというわけなのです。これも割り切りですので、ご了承ください。
(2) Import方法
CSVデータを指定ディレクトリに格納しておき、そこから全件入れ替えていきます。レコード単位のメンテナンスもできますが、1件単位で入力するのは面倒なので、想定していません。
下記のようなコードで格納していきます。
manager = get_manager(database_name, database_connect)
manager.define()
ret_code = manager.import_csv(fname);
manager.close()
[3] 他のデータベース
個人データですから、SQLite3で十分なのですが、オプションとして他のRDBに切り替えることも可能にしてあります。これについては、後述します。
[4] ファイル一覧
listdb.py : ListDB class
listdata.py : ListData class
manager.py : Manager interface
dbmanager.py : Database manager
dbutils.py : Database utilities
dbinterface.py : Database interface
dbsqlite3.py : SQLite3
dbmysql.py : MySQL
dbpostgres.py : Postgres
urlanalyze.py : URL encode
ソースについては、後ほどまとめて公開する予定です。
次回は、ListDBで使用するデータを収集していきましょう。