ORM

ORM

  ORM是Object-Relational Mapping的缩写,即对象关系映射。在Python中,ORM是将关系型数据库与Python代码之间做映射,也就是相当于屏蔽了对SQL语句的处理,只需调用ORM提供的API,即可操作数据库。Python中有多个ORM,例如:

  其中使用比较多的是Django中的ORM和SQLAlchemy,Django的ORM是内嵌到Django中的,通常只能在Django中使用;而SQLAlchemy是独立的第三方库,可以在很多项目中使用。
  通常,将数据库中的表映射为类,通常命名为Model;将表中的记录(行)映射为类中的属性,通常命名为Field。
  ORM通常的用法,参考:django Models。基本用法如下面代码所示:

import models

class Person(models.Model):
    name = models.CharField('username')
    shirt_size = models.IntField('shirtsize')

p = Person(name="Fred Flintstone", shirt_size=170)
p.save()
p.shirt_size

  我们来尝试编写一套简单的ORM,也就是需要编写模块models。首先先定义Field类:

class Field(object):
    def __init__(self, name, column_type):
        self.name = name
        self.column_type = column_type
    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)

  然后从Field派生出与数据库字段对应的类,这里选择字符串和整型为例:

class CharField(Field):
    def __init__(self, name):
        super(CharField, self).__init__(name, 'varchar(50)')

class IntField(Field):
    def __init__(self, name):
        super(IntField, self).__init__(name, 'int')

  接下来我们需要实现Model类。要实现Model类,我们先实现一个元类ModelMeta。这个元类ModelMeta扫描类的属性,将Filed类型的属性收集起来保存到__mappings__中,将类名称的小写作为表名,保存到__table__中。

class ModelMeta(type):
    def __new__(cls, name, bases, attrs):
        if name=='Model':
            return super(ModelMeta,cls).__new__(cls, name, bases, attrs)
        mappings = dict()
        for key, value in attrs.items():
            if isinstance(value, Field):
                print('Found mapping: %s==>%s' % (key, value))
                mappings[key] = value
        for key in mappings.keys():
            attrs.pop(key)
        attrs['__table__'] = name.lower()
        attrs['__mappings__'] = mappings
        return super(ModelMeta,cls).__new__(cls, name, bases, attrs)

  然后,使用元类定义类Model:

class Model(dict, metaclass=ModelMeta):
    def __init__(self, **kw):
        super(Model, self).__init__(**kw)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(r"'Model' object has no attribute '%s'" % key)

    def __setattr__(self, key, value):
        self[key] = value

    def save(self):
        fields = []
        params = []
        args = []
        for key, value in self.__mappings__.items():
            fields.append(value.name)
            params.append('?')
            args.append(getattr(self, key, None))
        sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
        print('sql: %s' % sql)
        print('args: %s' % str(args))

  到此,我们构建ORM的代码就完成了。执行使用ORM的代码,可以看到其输出:

Found mapping: name==>
Found mapping: shirt_size==>
sql: insert into person (username,shirtsize) values (?,?)
args: ['Fred Flintstone', 170]

  以上就是一个简单的ORM系统。这个ORM系统实现了展示了ORM的主要内容。这个ORM系统到实际使用的ORM还有很多需要添加和完善的地方,例如:对数据库的操作我们使用输出来模拟,实际上需要替换成真正操作数据库的语句;除了CharFiled和InitFiled,还要添加其它与数据库字段相关的类(例如:DateField、BinaryField);除了保存记录的方法save()还需要其它操作数据库的方法(例如:查询、更新、删除)。

参考:
  Python’s SQLAlchemy vs Other ORMs
  django Models