1 orm:就是將對象與關係數據庫建立一種映射關係,精確的,一對一的,保證你對對象的某一個操作,比如修改對象屬性,創建新的對象等,唯一的對應數據的一種修改數據的操作或者增加數據的操作.orm框架就是提供這種操作的,用戶只需定義一個類,就可以用對象的方法屬性來操作數據庫.
class User(Model): # 定義類的屬性到列的映射: id = IntegerField('id') name = StringField('username') email = StringField('email') password = StringField('password') # 創建一個實例: u = User(id=12345, name='Michael', email='[email protected]', password='my-pwd') # 保存到數據庫: u.save()
2 一般的映射關係就是:
對象 | 關係數據庫 |
---|---|
類名 | 表的名字 |
類的實例 | 表中的一行數據 |
類的屬性 | 表的字段 |
3 主要技術就是採用元類動態創建類對象
3.1 定義元類:元類,實現動態創建需要的類.
class ModelMetaclass(type): def __new__(cls, name, bases, attrs): if name=='Model': return type.__new__(cls, name, bases, attrs) print('Found model: %s' % name) mappings = dict() for k, v in attrs.items(): if isinstance(v, Field): print('Found mapping: %s ==> %s' % (k, v)) mappings[k] = v for k in mappings.keys(): attrs.pop(k) attrs['__mappings__'] = mappings # 保存屬性和列的映射關係 attrs['__table__'] = name # 假設表名和類名一致 return type.__new__(cls, name, bases, attrs)
3.2 定義基類:提供基本的類操作方法.
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"'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value): self[key] = value def save(self): fields = [] params = [] args = [] for k, v in self.__mappings__.items(): fields.append(v.name) params.append('?') args.append(getattr(self, k, None)) sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params)) print('SQL: %s' % sql) print('ARGS: %s' % str(args))
3.3 定義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
的基礎上,進一步定義各種類型的Field
,比如StringField
,IntegerField
等等:
class StringField(Field): def __init__(self, name): super(StringField, self).__init__(name, 'varchar(100)') class IntegerField(Field): def __init__(self, name): super(IntegerField, self).__init__(name, 'bigint')
3.4 當用戶定義一個class User(Model)
時,Python解釋器首先在當前類User
的定義中查找metaclass
,如果沒有找到,就繼續在父類Model
中查找metaclass
,找到了,就使用Model
中定義的metaclass
的ModelMetaclass
來創建User
類,也就是說,metaclass可以隱式地繼承到子類,但子類自己卻感覺不到。
在ModelMetaclass
中,一共做了幾件事情:
排除掉對
Model
類的修改;在當前類(比如
User
)中查找定義的類的所有屬性,如果找到一個Field屬性,就把它保存到一個__mappings__
的dict中,同時從類屬性中刪除該Field屬性,否則,容易造成運行時錯誤(實例的屬性會遮蓋類的同名屬性);把表名保存到
__table__
中,這裏簡化爲表名默認爲類名。
在Model
類中,就可以定義各種操作數據庫的方法,比如save()
,delete()
,find()
,update
等等。
我們實現了save()
方法,把一個實例保存到數據庫中。因爲有表名,屬性到字段的映射和屬性值的集合,就可以構造出INSERT
語句。參考廖雪峯python元類.https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319106919344c4ef8b1e04c48778bb45796e0335839000