Python編寫ORM框架
ORM全稱“Object Relational Mapping”,即物件-關係對映,就是把關係資料庫的一行對映為一個物件,也就是一個類對應一個表,這樣,寫程式碼更簡單,不用直接操作SQL語句。
要編寫一個ORM框架,所有的類都只能動態定義,因為只有使用者才能根據表的結構定義出對應的類來,使用 metaclass 。
編寫底層模組的第一步,就是先把呼叫介面寫出來。比如,使用者如果使用這個ORM框架,想定義一個User類來操作對應的資料庫表User,我們期待他寫出這樣的程式碼,用起來和litepal
差不多:
class User(Model):
id = IntegerField("id" )
username = StringField("username")
password = StringField("password")
email = StringField("email")
# 建立例項
u = User(id=1, username= "TaoYuan", password="123456", email="[email protected]")
u.save() # 儲存到資料庫
其中,父類Model和屬性型別StringField、IntegerField是由ORM框架提供的,剩下的魔術方法比如save()全部由metaclass自動完成。雖然metaclass的編寫會比較複雜,但ORM的使用者用起來卻異常簡單。
實現
首先來定義Field類,它負責儲存資料庫表的欄位名和欄位型別:
class Field(object):
def __init__(self, name, column_type):
self.name = name
self.column_type = column_type
def __str__(self,):
return "<%s:%s>" % (self.__class__.__name__, self.name)
在Field的基礎上,進一步定義各種型別的Field,比如StringField,IntegerField等等:
class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, "bigint")
class StringField(Field):
def __init__(self, name):
super(StringField, self).__init__(name, "varchar(20)")
就是編寫最複雜的ModelMetaclass以及Model了:
class ModelMetaclass(type):
def __new__(mcs, name, bases, attrs):
if name == "Model":
return type.__new__(mcs, name, bases, attrs)
print("Found Model:%s" % name)
mappings = dict()
for k, v in attrs.items():
if isinstance(v, Field):
print("Found mappings:%s --> %s" % (k, v))
mappings[k] = v
for k in mappings.keys():
attrs.pop(k)
attrs['__mappings__'] = mappings # 儲存屬性和列的對映關係
attrs['__table__'] = name # 假設表名和類名一致
return type.__new__(mcs, name, bases, attrs)
class Model(dict, metaclass=ModelMetaclass):
def __init__(self, **kw):
super(Model, self).__init__(**kw)
def __getattr__(self, key): # 屬性校驗
try:
return self[key]
except KeyError:
raise AttributeError(r"'Model' object has no attribute '%s'" % key)
def __setattr__(self, key, value): # set
self[key] = value
def save(self): # 儲存
fields = []
params = []
args = []
for k, v in self.__mappings__.items():
fields.append(v.name)
params.append('?')
args.append(getattr(self, k, None))
# 連線資料庫驅動即可真正連線
sql = "insert into %s (%s) values (%s)" % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args))
def delete(self): # 刪
# 連線資料庫驅動即可真正連線
sql = "delete from %s" % self.__table__
print('SQL: %s' % sql)
def update(self): # 改
fields = []
params = []
args = []
for k, v in self.__mappings__.items():
fields.append(v.name)
params.append('?')
args.append(getattr(self, k, None))
# 連線資料庫驅動即可真正連線
sql = "update %s set %s=%s" % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args))
def find(self): # 查
# 連線資料庫驅動即可真正連線
sql = "select * from %s" % self.__table__
print('SQL: %s' % sql)
當用戶定義一個class User(Model)
時,Python直譯器首先在當前類User
的定義中查詢metaclass
,如果沒有找到,就繼續在父類Model
中查詢metaclass
,找到了,就使用Model
中定義的metaclass
的ModelMetaclass
來建立User
類,也就是說,metaclass
可以隱式地繼承到子類,但子類自己卻感覺不到。
在ModelMetaclass
中,一共做了幾件事情:
- 排除掉對
Model
類的修改; - 在當前類(比如User)中查詢定義的類的所有屬性,如果找到一個Field屬性,就把它儲存到一個
__mappings__
的dict中,同時從類屬性中刪除該Field屬性,否則,容易造成執行時錯誤(例項的屬性會遮蓋類的同名屬性); - 把表名儲存到
__table__
中,這裡簡化為表名預設為類名。
在Model
類中,就可以定義各種操作資料庫的方法,比如save()
,delete()
,find()
,update
等等。
我們實現了save()
方法,把一個例項儲存到資料庫中。因為有表名,屬性到欄位的對映和屬性值的集合,就可以構造出INSERT
語句。
得到輸出:
Found Model:User
Found mappings:id --> <IntegerField:id>
Found mappings:username --> <StringField:username>
Found mappings:password --> <StringField:password>
Found mappings:email --> <StringField:email>
SQL: insert into User (id,username,password,email) values (?,?,?,?)
ARGS: [1, 'TaoYuan', '123456', '[email protected]']
------------------------------
SQL: delete from User
------------------------------
SQL: update User set id,username,password,email=?,?,?,?
ARGS: [1, 'TaoYuan', '123456', '[email protected]']
------------------------------
SQL: select * from User
小結
metaclass是Python中非常具有魔術性的物件,它可以改變類建立時的行為。這種強大的功能使用起來務必小心。
相關推薦
Python編寫ORM框架
ORM全稱“Object Relational Mapping”,即物件-關係對映,就是把關係資料庫的一行對映為一個物件,也就是一個類對應一個表,這樣,寫程式碼更簡單,不用直接操作SQL語句。 要編寫一個ORM框架,所有的類都只能動態定義,因為只有使用者才能根
Python中的元類編寫ORM框架
部落格轉載: https://blog.csdn.net/givemefive_y/article/details/79806348 https://blog.csdn.net/eye_water/article/details/78777870 https://www.liaoxue
Python的ORM框架SQLAlchemy使用入門(一)
不要放棄你的幻想。當幻想沒有的時候,你還可以生存,但是你雖生猶死。 建立實體類,生成資料庫架構 import os import sys from sqlalchemy import Col
編寫ORM框架
ORM:Object-Relational Mapping,把關係資料庫中的表結構對映到物件上。然後操作資料庫就不需要構造SQL語句,而是直接呼叫相應的方法。ORM框架可以方便的完成這些轉換,然後,資料庫表中的一行記錄就對應著python中的一個物件,就不需要使
推薦python的ORM框架peewee(轉)
以下是自己在一些專案中的簡單心得,無他,旨在向一些不瞭解peewee的新手推薦一個順手的工具,提供開發效率。至於具體使用細節,官方文件還是讀一下吧,簡單的文字。 熟手跳過。 你操作資料庫時在用繁瑣難維護的SQL?還是笨重複雜的SqlAlchemy?或者是你運氣夠好使用DJANGO而享受其ORM? 我曾經也是
深入理解Java的Annotation系列-第五部分 使用註解編寫ORM框架
一、什麼是ORM? 物件關係對映(英語:(Object Relational Mapping,簡稱ORM,或O/RM,或O/Rmapping),是一種程式技術,隨著面向物件的發展而產生的。用來把物件模型表示的物件對映到基於S Q L 的關係模型資料庫結構中去,或者把表中的
Python ORM框架之 Peewee入門
lob shortcuts pymysql 主鍵 也會 roo username fault 有意思 之前在學Django時,發現它的模型層非常好用,把對數據庫的操作映射成對類、對象的操作,避免了我們直接寫在Web項目中SQL語句,當時想,如果這個模型層可以獨立出來使用
python——type()、metaclass元類和精簡ORM框架
定制 定義 attribute varchar elm cep 實例 編寫代碼 __main__ 1、type()函數 #type()函數既可以返回一個對象的類型,又可以創建出新的類型, # 比如,我們可以通過type()函數創建出Hello類,而無需通過cl
python(十二)下:ORM框架SQLAlchemy使用學習
func column bar 插入數據 ref min 統計 就是 連接 此出處:http://blog.csdn.net/fgf00/article/details/52949973 本節內容 ORM介紹 sqlalchemy安裝 sqlalchemy
我的第一個python web開發框架(24)——系統重構與ORM
內容 版權 質量 重寫 很多 掌握 orm .... 最重要的 小白弄完代碼版本管理和接口文檔後,興奮的找到老菜。 小白:老大,我已經按你講的要求,將代碼版本管理和接口文檔都搞好了。從項目開始到現在,除了代碼編寫,感覺學會好多東西啊。 老菜:嗯嗯,實戰確實需
6、第八周 - 網絡編程進階 - Python語言下的SqlAlchemy ORM框架應用
() bind chan base pymysql commit 提交 輸出 echo Mysql SqlAlchemy 基本步驟 1、SqlAlchemy 基本結構語法如下: 案例: from sqlalchemy import create_engine,Colu
Python中Web框架編寫學習心得
記錄日誌 實例 心得 ret NPU oba esp ascii edi 學習廖雪峰老師的Python實戰教程,在Web框架這部分看了大致一個多禮拜,前面的知識學的不夠紮實,由於比較復雜,因此在這裏總結下,也算是鞏固了。 先看下框架的調用代碼: app = web.Ap
[python] 理解metaclass並實現一個簡單ORM框架
lds asc into password 這樣的 內容 建行 ati 什麽 metaclass 除了使用type()動態創建類以外,要控制類的創建行為,還可以使用metaclass。 metaclass,直譯為元類,簡單的解釋就是: 當我們定義了類以後,就可以根據這個
python ORM 框架 sqlalchemy
sqlalchemy 是一款Python語言寫的ORM框架, 該框架建立在資料庫API基礎之上。 sqlalchemy 本身無法操作資料庫,必須已第三方外掛為基礎,Dialect用於和資料API進行交流,根據不通的的配置呼叫不通的資料庫API,從而實現對資料庫的操作。
SQLAlchemy 1.2.15 釋出,Python ORM 框架
SQLAlchemy 1.2.15 釋出了,SQLAlchemy 是一個 Python 的 SQL 工具包以及資料庫物件關係對映框架。它包含整套企業級持久化模式,專門用於高效和高效能的資料庫訪問。 此版本包含了各種 ORM 級的修復,其中包括 1.2.13 中的
Python ORM框架Pony —— 什麼是Pony ORM?
Pony是一種高階的物件關係對映器。ORM允許開發人員以物件的形式處理資料庫的內容。關係資料庫包含儲存在表中的行。但是,當使用高階面嚮物件語言編寫程式時,可以以物件的形式訪問從資料庫檢索的資料,這樣十分方便。Pony ORM是一個Python語言庫,允許您方便地處理在關係資料庫中儲存為行的物件。
python的Pony ORM框架總結
最近學校裡辦了python興趣班,剛學完python的基礎語法就講了這個Pony框架,以下是我上課記錄的某些關鍵點的筆記 Python 2提供了兩種字串型別 - str(位元組字串)和unicode(unicode字串),而在Python 3中,str型別表示unicode字串,並且剛剛刪除了u
Python ORM框架Pony —— Pony入門
安裝 要安裝Pony我們首先要安裝好pip,假設我們已經安裝完成pip,請在dos命令視窗下鍵入以下命令: pip install pony 之後pip會自動將我們的Pony安裝到Python 2.7或Python 3上 要確保已成功安裝Pony,請以互動方式啟動Python編譯器並
一個用Python編寫的股票資料(滬深)爬蟲和選股策略測試框架
一個股票資料(滬深)爬蟲和選股策略測試框架,資料基於雅虎YQL和新浪財經。 根據選定的日期範圍抓取所有滬深兩市股票的行情資料。 根據指定的選股策略和指定的日期進行選股測試。 計算選股測試實際結果(包括與滬深300指數比較)。 儲存資料到JSON檔案、CS
python之Django框架篇-路由系統,檢視,模板,ORM複習
1. Urls.py 路由系統: 正則 分組匹配 --> 位置引數 分組命名匹配 --> 關鍵字引數 分級路由 include 給路由起別名 name="xx" 反向解析url view