利用metaclass元类实现ORM

精选30+云产品,助力企业轻松上云!>>> hot3.png

关键信息是Model类的父类是dict,我们在构建Model的时候传入的参数会被用来初始化一个dict。所以我们创建数据实例的时候数据的名称和数据值的映射会被存储在dict当中,所以我们在save方法当中才会从self的attr当中获取字段的值。并且我们在初始化User的时候,也必须要填写每个字段的名称,原因就在这里

代码如下:

class Field:
	def __init__(self, name, column_type):
		self.name = name
		self.column_type = column_type
	
	def __str__(self):
		return f"<{self.__class__.__name__}:{self.name}>"


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")


class ModelMetaclass(type):
	def __new__(cls, name, bases, attrs):
		if name == "Model":
			return type.__new__(cls, name, bases, attrs)
		print(f"Found Model:{name}")
		
		mappings = dict()
		for k, v in attrs.items():
			if isinstance(v, Field):
				print(f"Found Mapping:{k} ==> {v}")
				mappings[k] = v
		
		for k in mappings.keys():
			attrs.pop(k)
		attrs["__mappings__"] = mappings
		attrs["__tables__"] = name
		return type.__new__(cls, name, bases, attrs)


class Model(dict, metaclass=ModelMetaclass):
	def __init__(self, **kwargs):
		super(Model, self).__init__(**kwargs)
		
	def __getattr__(self, key):
		try:
			return self[key]
		except KeyError:
			raise AttributeError(f"'Model' object has not attrbute {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))


class User(Model):
	id = IntegerField("id")
	name = StringField("name")
	email = StringField("email")
	password = StringField("password")
	age = IntegerField("age")


u = User(id=12345, name='Michael', email='[email protected]', password="my-psd", age=1)

u["name1"] = "sdalsjdkl"

print(u)

u.save()

"""
Found Model:User
Found Mapping:id ==> 
Found Mapping:name ==> 
Found Mapping:email ==> 
Found Mapping:password ==> 
Found Mapping:age ==> 
{'id': 12345, 'name': 'Michael', 'email': '[email protected]', 'password': 'my-psd', 'age': 1, 'name1': 'sdalsjdkl'}
"""

你可能感兴趣的:(python,orm,redis,ceph,hash)