程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> Python中編寫ORM框架的入門指引

Python中編寫ORM框架的入門指引

編輯:更多關於編程

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

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

      ?

    1 user = User.get('123')

      而不是寫SQL然後再轉換成User對象:

      ?

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

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

      設計ORM接口

      和設計db模塊類似,設計ORM也是從上層調用者角度來設計。

      我們先考慮如何定義一個User對象,然後把數據庫表users和它關聯起來。

      ?

    1 2 3 4 5 6 from transwarp.orm import Model, StringField, IntegerField   class User(Model): __table__ = 'users' id = IntegerField(primary_key=True) name = StringField()

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

      ?

    1 2 3 4 # 創建實例: user = User(id=123, name='Michael') # 存入數據庫: user.insert()

      實現ORM模塊

      有了定義,我們就可以開始實現ORM模塊。

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

      ?

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 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的功能,同時又實現了特殊方法__getattr__()和__setattr__(),所以又可以像引用普通字段那樣寫:

      ?

    1 2 3 4 >>> user['id'] 123 >>> user.id 123

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

      ?

    1 2 3 4 5 6 7 8 9 10 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掃描映射關系,並存儲到自身的class中。

      然後,我們往Model類添加class方法,就可以讓所有子類調用class方法:

      ?

    1 2 3 4 5 6 7 8 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類就可以通過類方法實現主鍵查找:

      user = User.get('123')

      往Model類添加實例方法,就可以讓所有子類調用實例方法:

      ?

    1 2 3 4 5 6 7 8 9 10 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實例存入數據庫:

      ?

    1 2 user = User(id=123, name='Michael') user.insert()

      最後一步是完善ORM,對於查找,我們可以實現以下方法:

      ?

    1 2 3 4 5 find_first()   find_all()   find_by()

      對於count,可以實現:

      ?

    1 2 3 count_all()   count_by()

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

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

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved