利用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='test@leyantech.com', password="my-psd", age=1)

u["name1"] = "sdalsjdkl"

print(u)

u.save()

"""
Found Model:User
Found Mapping:id ==> <IntegerField:id>
Found Mapping:name ==> <StringField:name>
Found Mapping:email ==> <StringField:email>
Found Mapping:password ==> <StringField:password>
Found Mapping:age ==> <IntegerField:age>
{'id': 12345, 'name': 'Michael', 'email': 'test@leyantech.com', 'password': 'my-psd', 'age': 1, 'name1': 'sdalsjdkl'}
"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值