跬步 On Coding

ORM 对象关系映射

ORM概念

wikipedia: 对象关系映射

简单的说ORM就是通过操作Python中的对象来实现对关系数据库(MySQL)中数据的操作。Model类与数据库表映射,Model对象与数据库中的行映射,对象的属性与表中的字段映射。

用Python实现基本功能的ORM

首先定义Field类,代表DB中tabale的每一个字段,对象初始化的时候需要定义的属性有,字段名称,字段数据类型,是否为主键,是否可为空,字段默认值,是否可更改等字段属性

class Field(object):
    def __init__(self, **kw):
        self.name = kw.get('name', None)
        self._default = kw.get('default', None)
        self.primary_key = kw.get('primary_key', False)
        self.nullable = kw.get('nullable', True)
        self.updateable = kw.get('updateable', True)
        self.insertable = kw.get('insertable', True)
        self.datatype = kw.get('datatype', None)
        self.auto_increment = kw.get('increment', False)

Field是所有其它Field的父类,通过Field可派生出不同数据类型的子类,如:

class StringField(Field):
    def __init__(self, **kw):
        if not 'default' in kw:
            kw['default'] = ''
        if not 'datatype' in kw:
            kw['datatype'] = 'varchar(255)'
        super(StringField, self).__init__(**kw)

这里定义了一个字符串类型的子类。那么如何来定义一个表呢。想像以下,一个类映射DB中的表,类的实例映射表中的一行数据。

class User(Mode):
    __table__ = 'user'
    id = IntegerField(primary_key=True)
    name = StringField()

# 直接通过类方法来查询
user = User.get('123')

# 创建实例:
user = User(id=123, name='Michael')
# 存入数据库:
user.insert()

这里定义了一个user表有2个字段,然后就可用操作了,通过类方法SELECT查询,实例方法INSERT UPDATE DELETE
要实现ORM需要定义一个Mode类,所有的表映射都是Mode的子类。表的实例中一个字段的值与字段名称是key-value的关系,所以dict可用作为Mode的父类。

class Mode(dict):
    __metaclass__ = ModelMetaClass
    def __init__(self, *args, **kw):
        super(Mode, self).__init__(*args, **kw)

元类ModelMetaClass所做的事情就是拦截Mode类的创建,获取所有的类属性,如果发现类属性为Field的子类,则建立映射关系。

class ModelMetaClass(type):
    def __new__(cls, name, bases, attrs):
        mapping = {}
        for k, v in attrs.iteritems():
            if instance(v, Field):
                mapping[k] = v
        for k in mapping.keys()
            attrs.pop(k)
        attrs['__mapping__'] = mapping
        super(ModelMetaClass, cls).__new__(cls, name, bases, attrs)

这样就建立了映射关系,然后实现Mode类的类方法与实例方法。就能操作数据库了。

参考

orm.py
编写ORM