python使用metaclass实现ORM框架

wang 发表于 Pyhon 分类,标签:
# -*- coding: utf-8 -*-

'''
	python使用metaclass实现ORM框架

'''

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)


class StringField(Field):

	def __init__(self,name):
		super(StringField, self).__init__(name,'varchar(100)')
		# 可以写成super().__init__(name,'varchar(100)')

class IntegerField(Field):

	def __init__(self,name):
		super(IntegerField,self).__init__(name,'bigint')


class ModelMetaclass(type):

	# __new__ 方法的参数就是 class type(name, bases, dict)
	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():
			# 记录Field的子类属性
			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)


class Model(dict, metaclass = ModelMetaclass):
	'''
	继承dict,并传入metaclass参数
	当我们传入关键字参数metaclass时,魔术就生效了,
	它指示Python解释器在创建MyList时,要通过ListMetaclass.__new__()来创建,
	在此,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。

	__new__()方法接收到的参数依次是:
	当前准备创建的类的对象;
	类的名字;
	类继承的父类集合;
	类的方法集合。
	'''

	def __init__(self, **kw):
		super(Model, self).__init__(**kw)

	def __getattr__(self, key):
		try:
			return self[key]
		except KeyError:
			raise AttributeError(r"'%s' object has no attribute '%s'" % (self.__class__.__name__, 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))

		sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
		print("SQL:%s" % sql)
		print("args:%s" % str(args))		



# test code:

class User(Model):
	id = IntegerField('id')
	name = StringField('username')
	email = StringField('email')
	password = StringField('password')


u = User(id = 123, name = 'huhu', email = 'test@163.org', password = 'pwd')

u.save()

print(u.name)


这是学习python是偶然看到的,来源是:

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319106919344c4ef8b1e04c48778bb45796e0335839000#0


0 篇评论

发表我的评论