# -*- coding: utf-8 -*-
# @Time : 2021/8/1 19:13
# @Author : zy7y
# @Gitee : https://gitee.com/zy7y
# @File : metaclass_orm.py
# @Project : PythonBooks
import numbers
# 数据描述符 定义
class Field:
pass
class IntField(Field):
def __init__(self, db_column, min_value=None, max_value=None):
self._value = None
self.db_column = db_column
self.min_value = min_value
self.max_value = max_value
if min_value is not None:
if not isinstance(min_value, numbers.Integral):
raise ValueError("min_value 必须是 int 类型")
elif min_value < 0:
raise ValueError("min_value 必须 大于 0 ")
if not isinstance(max_value, numbers.Integral):
raise ValueError("max_value 必须是 int 类型")
elif max_value < 0:
raise ValueError("max_value 必须 大于 0 ")
def __get__(self, instance, owner):
return self._value
def __set__(self, instance, value):
self._value = value
class CharField(Field):
def __init__(self, db_column, max_length=None):
self._value = None
self.db_column = db_column
self.max_length = None
if max_length is None:
raise ValueError("max_length 不能为None")
def __get__(self, instance, owner):
print(owner)
return self._value
def __set__(self, instance, value):
if not isinstance(value, str):
raise ValueError("value 必须是 字符串")
# if len(value) > self.max_length:
# raise ValueError("超出长度")
# 元类定义
class ModelMetaClass(type):
"""元类定义 把字段 和元类信息进行处理 在加到 类属性中"""
def __new__(cls, name, bases, attrs, **kwargs):
print(attrs)
fields = {} # 存字段
for key, value in attrs.items():
if isinstance(value, Field):
fields[key] = value
attrs_meta = attrs.get("Meta", None)
_meta = {} # 存元类数据
db_table = name.lower()
if attrs_meta is not None:
table = getattr(attrs_meta, "db_table", None)
if table is not None:
db_table = table
del attrs["Meta"]
_meta["db_table"] = db_table
attrs["_meta"] = _meta
attrs["fields"] = fields
return super().__new__(cls, name, bases, attrs, **kwargs)
class BaseModel(metaclass=ModelMetaClass):
def __init__(self, *args, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
return super().__init__()
def save(self):
fields = []
values = []
for key, value in self.fields.items():
db_column = value.db_column
if db_column is None:
db_column = key.lower()
fields.append(db_column)
value = getattr(self, key)
values.append(value)
sql = f"insert into {db_column} ({fields}) values ({values})"
print(sql)
class User(BaseModel):
name = CharField(db_column="name", max_length=10)
age = IntField(db_column="age", min_value=0, max_value=100)
class Meta:
db_table = "user"
if __name__ == '__main__':
user = User()
user.name = "zy7y"
user.age = 1
user.save()