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

來源:互聯網
上載者:User

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是不是很容易呢?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.