python:改良廖雪峰的使用元类自定义ORM
概要
本文仅仅是对廖雪峰老师的使用元类自定义ORM进行改进,并不是要创建一个ORM框架
编写fieldclass Field(object): def __init__(self, column_type,max_length,**kwargs): ''' 1,删除了参数name,field参数全部为定义字段类型相关参数,和众多有名的orm相同 2,使用反射,方便字段的扩展,如本例使用deafault就是反射的应用 ''' self.column_type = column_type #字段类型 self.max_length=max_length #字段长度 self.default=None #字段默认值,如果想扩展可以填写更多的参数 if kwargs: for k,v in kwargs.items(): if hasattr(self,k): setattr(self,k,v) def __str__(self): return '<%s>' % (self.__class__.__name__) class StringField(Field): def __init__(self,max_length,**kwargs): super().__init__(column_type='varchar({})'.format(max_length),max_length=max_length,**kwargs) class IntegerField(Field): def __init__(self,**kwargs): super().__init__(column_type='bigint',max_length=8)编写metaclass
class ModelMetaclass(type): def __new__(cls, name, bases, attrs): if name=='Model': return type.__new__(cls, name, bases, attrs) mappings = dict() for k, v in attrs.items(): #print('k={},v={}'.format(k,v)) if isinstance(v, Field): mappings[k] = v for k in mappings.keys(): attrs.pop(k) attrs['__mappings__'] = mappings # 保存属性和列的映射关系 attrs['__table__'] = attrs.get('Meta').table or name # 假设表名和类名一致 return type.__new__(cls, name, bases, attrs)编写model
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 = [] for k, v in self.__mappings__.items(): fields.append(k) params.append(getattr(self, k,v.default)) sql = 'insert into {} ({}) values ({})'.format(self.__table__, self.join(fields) ,self.join(params)) print('SQL: %s' % sql) #自己写了一个join函数,廖雪峰老师使用自带join,无法处理数字等非字符串类型 import functools def join(self,attrs,pattern=','): return functools.reduce(lambda x,y:'{}{}{}'.format(x,pattern,y),attrs)测试
class User(Model): #使用Meta,能自定义表的相关信息 class Meta: #自定义表名 table='users' # 定义类的属性到列的映射: id = IntegerField() name = StringField(max_length=50) email = StringField(max_length=50,default='[email protected]') password = StringField(max_length=50) if __name__=="__main__": # 创建一个实例: u=User(id=234,name='jane',password='pwd') # 保存到数据库: u.save() #打印结果;SQL: insert into users (id,name,email,password) values (234,jane,[email protected],pwd)引用
1, 廖雪峰:使用元类
2, github:本文源码
相关推荐
honghao0 2017-03-02
PythonGCS 2019-04-20
sdwylry 2018-11-29
ciqingloveless 2019-10-24
BITSKY 2019-07-10
orlandowww 2019-07-08
bnmcvzx 2019-07-01
chunjiekid 2019-06-28
yuan00yu 2019-06-28
chunjiekid 2019-06-27
Lenskit 2019-06-26
小方哥哥 2019-06-21
mayflowers 2019-06-21
子藤 2019-06-04
Yasin 2019-04-23
学习备忘录 2019-04-21
HMHYY 2019-04-21
弗泽智能 2019-04-21