Python中編寫ORM框架的入門指引
來源:易賢網(wǎng) 閱讀:1732 次 日期:2015-04-30 13:50:43
溫馨提示:易賢網(wǎng)小編為您整理了“Python中編寫ORM框架的入門指引”,方便廣大網(wǎng)友查閱!

這篇文章主要介紹了Python中編寫ORM框架的入門指引,示例代碼基于Python2.x版本,需要的朋友可以參考下

有了db模塊,操作數(shù)據(jù)庫直接寫SQL就很方便。但是,我們還缺少ORM。如果有了ORM,就可以用類似這樣的語句獲取User對象:

user = User.get('123')

而不是寫SQL然后再轉(zhuǎn)換成User對象:

u = db.select_one('select * from users where id=?', '123')

user = User(**u)

所以我們開始編寫ORM模塊:transwarp.orm。

設(shè)計ORM接口

和設(shè)計db模塊類似,設(shè)計ORM也是從上層調(diào)用者角度來設(shè)計。

我們先考慮如何定義一個User對象,然后把數(shù)據(jù)庫表users和它關(guān)聯(lián)起來。

from transwarp.orm import Model, StringField, IntegerField

class User(Model):

__table__ = 'users'

id = IntegerField(primary_key=True)

name = StringField()

注意到定義在User類中的__table__、id和name是類的屬性,不是實(shí)例的屬性。所以,在類級別上定義的屬性用來描述User對象和表的映射關(guān)系,而實(shí)例屬性必須通過__init__()方法去初始化,所以兩者互不干擾:

# 創(chuàng)建實(shí)例:

user = User(id=123, name='Michael')

# 存入數(shù)據(jù)庫:

user.insert()

實(shí)現(xiàn)ORM模塊

有了定義,我們就可以開始實(shí)現(xiàn)ORM模塊。

首先要定義的是所有ORM映射的基類Model:

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"'Dict' object has no attribute '%s'" % key)

def __setattr__(self, key, value):

self[key] = value

Model從dict繼承,所以具備所有dict的功能,同時又實(shí)現(xiàn)了特殊方法__getattr__()和__setattr__(),所以又可以像引用普通字段那樣寫:

>>> user['id']

123

>>> user.id

Model只是一個基類,如何將具體的子類如User的映射信息讀取出來呢?答案就是通過metaclass:ModelMetaclass:

class ModelMetaclass(type):

def __new__(cls, name, bases, attrs):

mapping = ... # 讀取cls的Field字段

primary_key = ... # 查找primary_key字段

__table__ = cls.__talbe__ # 讀取cls的__table__字段

# 給cls增加一些字段:

attrs['__mapping__'] = mapping

attrs['__primary_key__'] = __primary_key__

attrs['__table__'] = __table__

return type.__new__(cls, name, bases, attrs)

這樣,任何繼承自Model的類(比如User),會自動通過ModelMetaclass掃描映射關(guān)系,并存儲到自身的class中。

然后,我們往Model類添加class方法,就可以讓所有子類調(diào)用class方法:

class Model(dict):

...

@classmethod

def get(cls, pk):

d = db.select_one('select * from %s where %s=?' % (cls.__table__, cls.__primary_key__.name), pk)

return cls(**d) if d else None

User類就可以通過類方法實(shí)現(xiàn)主鍵查找:

user = User.get('123')

往Model類添加實(shí)例方法,就可以讓所有子類調(diào)用實(shí)例方法:

class Model(dict):

...

def insert(self):

params = {}

for k, v in self.__mappings__.iteritems():

params[v.name] = getattr(self, k)

db.insert(self.__table__, **params)

return self

這樣,就可以把一個User實(shí)例存入數(shù)據(jù)庫:

user = User(id=123, name='Michael')

user.insert()

最后一步是完善ORM,對于查找,我們可以實(shí)現(xiàn)以下方法:

find_first()

find_all()

find_by()

對于count,可以實(shí)現(xiàn):

count_all()

count_by()

以及update()和delete()方法。

最后看看我們實(shí)現(xiàn)的ORM模塊一共多少行代碼?加上注釋和doctest才僅僅300多行。用Python寫一個ORM是不是很容易呢?

更多信息請查看IT技術(shù)專欄

更多信息請查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:Python中編寫ORM框架的入門指引
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機(jī)號
  • 驗證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報警專用圖標(biāo)