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

时间: 2024-08-24 10:58:41

Python中编写ORM框架的入门指引的相关文章

Python中的元类编程入门指引_python

回顾面向对象编程 让我们先用 30 秒钟来回顾一下 OOP 到底是什么.在面向对象编程语言中,可以定义 类,它们的用途是将相关的数据和行为捆绑在一起.这些类可以继承其 父类的部分或全部性质,但也可以定义自己的属性(数据)或方法(行为).在定义类的过程结束时,类通常充当用来创建 实例(有时也简单地称为 对象)的模板.同一个类的不同实例通常有不同的数据,但"外表"都是一样 - 例如, Employee 对象 bob 和 jane 都有 .salary 和 .room_number ,但两者

在Python中编写数据库模块的教程

  这篇文章主要介绍了在Python中编写数据库模块的教程,本文代码基于Python2.x版本,需要的朋友可以参考下 在一个Web App中,所有数据,包括用户信息.发布的日志.评论等,都存储在数据库中.在awesome-python-app中,我们选择MySQL作为数据库. Web App里面有很多地方都要访问数据库.访问数据库需要创建数据库连接.游标对象,然后执行SQL语句,最后处理异常,清理资源.这些访问数据库的代码如果分散到各个函数中,势必无法维护,也不利于代码复用. 此外,在一个Web

Python的Django框架使用入门指引_python

 前言 传统 Web 开发方式常常需要编写繁琐乏味的重复性代码,不仅页面表现与逻辑实现的代码混杂在一起,而且代码编写效率不高.对于开发者来说,选择一个功能强大并且操作简洁的开发框架来辅助完成繁杂的编码工作,将会对开发效率的提升起到很大帮助.幸运的是,这样的开发框架并不少见,需要做的仅是从中选出恰恰为开发者量身打造的那款Web框架. 自从基于 MVC 分层结构的 Web 设计理念普及以来,选择适合的开发框架无疑是项目成功的关键性因素.无论是 Struts.Spring 或是其他 Web 框架的出现

小巧优美的ORM框架-doodads入门指南

关于.net下的ORM框架,大家最为耳熟的可能就是NHibernate了,当然,很多公司正在使用自己开发的ORM框架,笔者至少见过3家不同公司的ORM框架,其实都是大同小异,借助于codesmith.mygeneration等代码生成工具,自己开发一个ORM框架也不是什么难事,关键的问题是,你能不能设计出代码优美简洁.功能灵活.定制方便以及部署容易的ORM框架. 我去年开始热衷NHibernate(与其说热衷,不如说是迷信,因为后来越来越多的证据证明,公司自己的那套用了几年的使用Excel生成实

艾伟:小巧优美的ORM框架-doodads入门指南[转载]

关于.net下的ORM框架,大家最为耳熟的可能就是NHibernate了,当然,很多公司正在使用自己开发的ORM框架,笔者至少见过3家不同公司的ORM框架,其实都是大同小异,借助于codesmith.mygeneration等代码生成工具,自己开发一个ORM框架也不是什么难事,关键的问题是,你能不能设计出代码优美简洁.功能灵活.定制方便以及部署容易的ORM框架. 我去年开始热衷NHibernate(与其说热衷,不如说是迷信,因为后来越来越多的证据证明,公司自己的那套用了几年的使用Excel生成实

Python下的subprocess模块的入门指引_python

在熟悉了Qt的QProcess以后,再回头来看python的subprocess总算不觉得像以前那么恐怖了. 和QProcess一样,subprocess的目标是启动一个新的进程并与之进行通讯.subprocess.Popen 这个模块主要就提供一个类Popen: class subprocess.Popen( args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, clos

用实例详解Python中的Django框架中prefetch_related()函数对数据库查询的优化_python

实例的背景说明 假定一个个人信息系统,需要记录系统中各个人的故乡.居住地.以及到过的城市.数据库设计如下: Models.py 内容如下:   from django.db import models class Province(models.Model): name = models.CharField(max_length=10) def __unicode__(self): return self.name class City(models.Model): name = models.

Python的Flask框架中Flask-Admin库的简单入门指引_python

 Flask-Admin是一个功能齐全.简单易用的Flask扩展,让你可以为Flask应用程序增加管理界面.它受django-admin包的影响,但用这样一种方式实现,开发者拥有最终应用程序的外观.感觉和功能的全部控制权. 本文是关于Flask-Admin库的快速入门.本文假设读者预先具有一些Flask框架的知识.     介绍     初始化     增加视图     身份验证     生成URL     模型视图     文件管理 介绍 这个库打算做到尽可能的灵活.并且开发者不需要任何猴子补

Python的ORM框架SQLObject入门实例_python

SQLObject和SQLAlchemy都是Python语言下的ORM(对象关系映射)解决方案,其中SQLAlchemy被认为是Python下事实上的ORM标准.当然,两者都很优秀. 一.安装 复制代码 代码如下: sudo pip install SQLObject 使用SQLObject操作mysql时候报错ImportError: No module named MySQLdb,那便安装MySQLdb: 复制代码 代码如下: sudo pip install MySQL-python 没想