勉強用にO/R Mapperを自作中
PyDumpFSをwin32対応にするための過程でsqliteを使うことにしたのでそれようのO/R Mapperを勉強がてら作っている。
実用に耐えるものが欲しいならSQLObjectとかSQLAlchemyとか使ったほうが良いんだろうけど、sqlite3モジュールを使うのは初めてだしO/R Mapperの動作の理解のためにも自分で一から書いてみると決めた。
使用するデーターベースエンジンはsqlite3決め打ち。sqliteが対応しない機能は対応しない。
O/R MapperとしてDjangoのそれしか使ったことがないので種類的にはActiveRecordになるのかな。Djangoのものは十分使いやすいので出来る限り構文は似せていきたい。
とりあえず今の段階で書けてるのはここまで:
#!/usr/bin/python # -*- coding: utf8 -*- import sqlite3 class DBField: """DBのフィールドを表すクラスの基底""" def __init__(self, unique=False, null=False, db_index=False, rel=None, default=None): """初期化""" self.unique = unique self.null = null self.db_index = db_index self.rel = rel self.default = default self.name = None def set_name(self,name): """フィールド名の設定""" self.name = name def getsql(self): """SQLの生成""" if self.name: ret = self.name + "text" return ret class DBTable: """ sqlite3決め打ちのO/R Mapper. クラス変数 connection : データベースへのコネクション """ connection = sqlite3.connect(":memory:") #サンプルとしてin-memory @classmethod def get_conection(cls): return cls.conection @classmethod def set_connection(cls, con): cls.connection = con @classmethod def get_table_sql(cls): """SQLの生成""" rownames = set(dir(cls)) ^ set(dir(DBTable)) columns = "" for rowname in rownames: row = getattr(cls, rowname) if hasattr(row, "getsql"): columns += row.getsql() + ",\n\t" sql = "create table if not exist %s (\n\tid INTEGR PRIMARY KEY," + \ "\t%s\n);" sql = sql%(cls.__name__, columns) return sql @classmethod def create_table(cls): """テーブルの生成""" cur = cls.get_connection().cursor() sql = cls.get_table_sql() cur.execute(sql) cur.close() cls.get_connection().commit() def __init__(self, **kw): rownames = set(dir(cls)) ^ set(dir(DBTable)) if "id" in kw.keys(): rownamess = ", ".join(rownames) tablename = self.__class__.__name__ sql = "select %s from %s where id=?"%(rownamess,tablename) cur = self.getconnection().cursor() cur.execute(sql, (kw["id"],)) for rowname, value in zip(rownames, cur.fetchone()): setattr(self, rowname, value) cur.close() elif kw: self.id=None for rowname in set(rownames) & set(kw.keys()): setattr(self, rowname, kw[rowname])