Torndbベースの簡易ORM
===============================================================================================================================
オリジナル作品は、転載を許可します。転載時は必ずハイパーリンクで元の出典と本声明を明示してください。
自己転記を明記してくださいhttp://yunjianfei.iteye.com/blog/
===============================================================================================================================
最近tonadoでReserviceサービスを提供しています。他のwebserverアプリケーションはURL、Resertを通じてアクセスします。
私たちはwebアプリケーションを開発する時、java eeでよく使われているhibernateやibatis、pythonのSQLAlchemyなどのORMの枠組みを考えることができます。ORMを使うと、ある程度の開発効率が上がります。
簡単なORMフレームワークは主に以下のような機能を実現すれば十分です。
1.挿入:クラスオブジェクトをデータベースレコードにマッピングする
2.クエリー:データベースレコードをクラスオブジェクトにマッピングする
3.修正、削除:自分でsql文を書くことで解決できます。
pythonには種類がありますが、dict辞書の種類もあります。もし辞書をクラスに包装すれば、移行包装に見えます。逆にフレキシブルではないので、精錬してください。pythonのORMの枠組みは以下のような点だけで十分です。
1.挿入:pythonのdictをデータベースレコードにマッピングする
2.クエリー:データベースレコードはpythonのdictおよびlistなどにマッピングされます。
3.修正、削除:自分でsql文を書くことで解決できます。
いくつかのテストを経て、技術選択型は最終的にtonadbを使用して、非常に軽量で、照会データベースから返されたオブジェクトは直接pythonのデータタイプdictまたはlistのようにマッピングされます。javaの「オブジェクト・属性」と同様にデータにアクセスすることができます。これは本当に気持ちいいです。まず、例を見てください。
出力結果は:
〈クラス〉_メーン.Row'
dic.name:hello
dic.num:12334
この例を通して、pythonの中のdictタイプは、javaの「オブジェクト・属性」のようにアクセスできるようになります。
tondbはこのようにして、検索したデータは「.列名」で直接アクセスできます。
検索する時は直接dictまたはlistタイプに戻りますが、挿入しますか?javaのように、一つの対象に入ることができれば、ORMフレームを通して直接にsqlに反射して操作するのが便利です。
それともdictですか?挿入する時、直接に挿入したデータフォーマットをdictとして保存して、このdictを通じてinsert文を生成すればいいです。各種の資料を調べて、次のような方法を抽出しました。
このように挿入する時、私達はもうくどいsql文を書かなくてもいいです。私達が挿入する対象をdictパッケージを使うだけです。
ホームリストがあります。中にhostname、ipの二つのフィールドがあります。次のコードを使って、データベースに挿入できます。
便利ですか?添付ファイルは私が修正した後、完全なtondbソースです。ダウンロードして使ってください。
バンドの一例として、完全版はgithubで発表したwebserviceフレームを参照してください。https://github.com/yunfeiflying/tornado-rest-web-service-framwork/
オリジナル作品は、転載を許可します。転載時は必ずハイパーリンクで元の出典と本声明を明示してください。
自己転記を明記してくださいhttp://yunjianfei.iteye.com/blog/
===============================================================================================================================
最近tonadoでReserviceサービスを提供しています。他のwebserverアプリケーションはURL、Resertを通じてアクセスします。
私たちはwebアプリケーションを開発する時、java eeでよく使われているhibernateやibatis、pythonのSQLAlchemyなどのORMの枠組みを考えることができます。ORMを使うと、ある程度の開発効率が上がります。
簡単なORMフレームワークは主に以下のような機能を実現すれば十分です。
1.挿入:クラスオブジェクトをデータベースレコードにマッピングする
2.クエリー:データベースレコードをクラスオブジェクトにマッピングする
3.修正、削除:自分でsql文を書くことで解決できます。
pythonには種類がありますが、dict辞書の種類もあります。もし辞書をクラスに包装すれば、移行包装に見えます。逆にフレキシブルではないので、精錬してください。pythonのORMの枠組みは以下のような点だけで十分です。
1.挿入:pythonのdictをデータベースレコードにマッピングする
2.クエリー:データベースレコードはpythonのdictおよびlistなどにマッピングされます。
3.修正、削除:自分でsql文を書くことで解決できます。
いくつかのテストを経て、技術選択型は最終的にtonadbを使用して、非常に軽量で、照会データベースから返されたオブジェクトは直接pythonのデータタイプdictまたはlistのようにマッピングされます。javaの「オブジェクト・属性」と同様にデータにアクセスすることができます。これは本当に気持ちいいです。まず、例を見てください。
import types
import time
class Row(dict):
"""A dict that allows for object-like property access syntax."""
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError(name)
dic = Row()
dic.name = 'hello'
dic.num = '12334'
print type(dic)
print "dic.name: " + dic.name
print "dic.num: " + dic.num
出力結果は:
〈クラス〉_メーン.Row'
dic.name:hello
dic.num:12334
この例を通して、pythonの中のdictタイプは、javaの「オブジェクト・属性」のようにアクセスできるようになります。
tondbはこのようにして、検索したデータは「.列名」で直接アクセスできます。
検索する時は直接dictまたはlistタイプに戻りますが、挿入しますか?javaのように、一つの対象に入ることができれば、ORMフレームを通して直接にsqlに反射して操作するのが便利です。
それともdictですか?挿入する時、直接に挿入したデータフォーマットをdictとして保存して、このdictを通じてinsert文を生成すればいいです。各種の資料を調べて、次のような方法を抽出しました。
def insert_by_dict(self, tablename, rowdict, replace=False):
cursor = self._cursor()
cursor.execute("describe %s" % tablename)
allowed_keys = set(row[0] for row in cursor.fetchall())
keys = allowed_keys.intersection(rowdict)
if len(rowdict) > len(keys):
unknown_keys = set(rowdict) - allowed_keys
logging.error("skipping keys: %s", ", ".join(unknown_keys))
columns = ", ".join(keys)
values_template = ", ".join(["%s"] * len(keys))
if replace:
sql = "REPLACE INTO %s (%s) VALUES (%s)" % (
tablename, columns, values_template)
else:
sql = "INSERT INTO %s (%s) VALUES (%s)" % (
tablename, columns, values_template)
values = tuple(rowdict[key] for key in keys)
try:
cursor.execute(sql, values)
#self._execute(cursor, sql, values, None)
return cursor.lastrowid
finally:
cursor.close()
このように挿入する時、私達はもうくどいsql文を書かなくてもいいです。私達が挿入する対象をdictパッケージを使うだけです。
ホームリストがあります。中にhostname、ipの二つのフィールドがあります。次のコードを使って、データベースに挿入できます。
host = {}
host['hostname'] = 'test1'
host['ip'] = '10.22.10.90'
ret = db.insert_by_dict("Host", host)
便利ですか?添付ファイルは私が修正した後、完全なtondbソースです。ダウンロードして使ってください。
バンドの一例として、完全版はgithubで発表したwebserviceフレームを参照してください。https://github.com/yunfeiflying/tornado-rest-web-service-framwork/
#!/usr/bin/env python2.7
#
# -*- coding:utf-8 -*-
#
# Author : YunJianFei
# E-mail : [email protected]
# Date : 2014/02/25
# Desc : Test db
#
""" Data Access Object
This file impelements DBI for the table 'Host'
The Host table's create sql is :
CREATE TABLE IF NOT EXISTS `test`.`Host` (
`host_id` INT NOT NULL AUTO_INCREMENT,
`host_type` INT NULL,
`hostname` VARCHAR(45) NULL,
`ip` VARCHAR(45) NULL,
`create_time` VARCHAR(45) NULL,
`cpu_count` INT NULL,
`cpu_pcount` INT NULL,
`memory` INT NULL,
`os` VARCHAR(200) NULL,
`comment` VARCHAR(200) NULL,
PRIMARY KEY (`host_id`))
ENGINE = InnoDB;
"""
from util.dbconst import TableName, TableFields, TableSelectSql
import logging
class HostDao:
def __init__(self, db):
mysql_host = "192.168.10.11:3306"
db_name = "test"
db_user = "root"
db_pass = ""
self.db = torndb.Connection(
host=mysql_host, database=db_name,
user=db_user, password=db_pass
)
def insert_by_dict(self, host, replace=False):
try:
id = self.db.insert_by_dict("Host", host, replace)
return id
except Exception, ex:
logging.error("Insert host failed! Exception: %s Host: %s", str(ex), str(host))
return None
def if_exist(self, hostname, ip):
ret = self.get_by_hostname(hostname)
if ret != None:
return True
ret = self.get_by_ip(ip)
if ret != None:
return True
return False
def get_by_ip(self, ip):
sql = TableSelectSql.HOST + " where ip='" + str(ip)+"'"
return self.db.get(sql)
def get_all(self):
sql = TableSelectSql.HOST
return self.db.query(sql)
def get_by_hostname(self, hostname):
sql = TableSelectSql.HOST + " where hostname='" + str(hostname)+"'"
return self.db.get(sql)
def get_by_id(self, host_id):
sql = TableSelectSql.HOST + " where host_id=%s" % str(host_id)
return self.db.get(sql)
def get_id_by_hostname(self, hostname):
sql = TableSelectSql.HOST + " where hostname='" + str(hostname)+"'"
ret = self.db.get(sql)
if ret != None:
return ret.host_id
return None
def update_worker_num_by_hostname(self, hostname, worker_num):
try:
sql = "UPDATE Host SET worker_num=%s WHERE hostname='%s'" % (worker_num, str(hostname))
ret = self.db.execute(sql)
return ret
except Exception, ex:
logging.error("Update Host failed! Exception: %s hostname: %s , worker_num: %s", str(ex), str(hostname), worker_num)
return None
def update_worker_num_by_id(self, host_id, worker_num):
try:
sql = "UPDATE Host SET worker_num=%s WHERE host_id=%s" % (worker_num, host_id)
ret = self.db.execute(sql)
return ret
except Exception, ex:
logging.error("Update Host failed! Exception: %s host_id: %s , worker_num: %s", str(ex), host_id, worker_num)
return None
def del_by_hostname(self, hostname):
try:
sql = "DELETE FROM Host WHERE hostname='" + str(hostname) + "'"
ret = self.db.execute(sql)
return ret
except Exception, ex:
logging.error("Delete host failed! Exception: %s hostname: %s", str(ex), str(hostname))
return None
def del_by_id(self, host_id):
try:
sql = "DELETE FROM Host WHERE host_id=" + str(host_id)
ret = self.db.execute(sql)
return ret
except Exception, ex:
logging.error("Delete host failed! Exception: %s host_id: %s", str(ex), host_id)
return None