通过元类简单的实现一个类似于django的orm

既然提到元类,那么什么是元类?

元类也就是创造类的类,在python中type就是一个元类

要实现django中的orm,首先要了解属性描述符,下面给出两个属性描述符

class Field:
    def __init__(self, min_lenth, max_lenth):
        self.min_lenth = min_lenth
        self.max_lenth = max_lenth
        if min_lenth >= max_lenth:
            raise ValueError("最小值应该比最大值小")



class InField(Field):
    """数据描述符"""
    def __init__(self, min_lenth, max_lenth):
        self._value = None
        super(InField, self).__init__(min_lenth, max_lenth)

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        if isinstance(value, numbers.Integral):
            if self.min_lenth:
                if value < self.min_lenth:
                    raise ValueError("必须大于等于最小值")
            if self.max_lenth:
                if value > self.max_lenth:
                    raise ValueError("必须小于最大值")
            self._value = value
        else:
            raise ValueError("参数必须输一个int类型")

    def __delete__(self, instance):
        pass


class CharField(Field):
    """数据描述符"""
    def __init__(self, min_lenth, max_lenth):
        self._value = None
        super(CharField, self).__init__(min_lenth, max_lenth)

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        self._value = value

    def __delete__(self, instance):
        pass

编写一个元类,这里要讲的就是,既然我们要用元类创建一个类,那么当我们创建这个类的对象的时候用__new__这个魔法函数去控制实例化,在其中注入一些属性

class BaseModel(type):
    """因为继承了type,那么BaseMode就是一个元类"""
    def __new__(cls, name, base, attr, **kwargs):
        """__new__魔法方法控制类的实例化"""
        # fields的作用是把我们属于数据描述符的字段抽取出来,最后操作数据的时候用到
        fields = dict()
        for key, value in attr.items():
            if isinstance(value, Field):
                fields[key] = value
        meta = attr.get("Meta")
        db_table = name.lower()
        if meta:
            data = meta.__dict__
            if "db_table" in data:
                db_table = data.get("db_table")
            attr["data"] = data
            del attr["Meta"]

        attr["db_table"] = db_table
        attr["fields"] = fields
        # 养成好习惯调用父类的方法返回
        return super().__new__(cls, name, base, attr, **kwargs)

创建一个model父类

# 创建这个的原因呢,是因为我们要实现类似django的orm功能,因此,这个类中我们需要写一些操作数据库的方法,这样代码看起来回更加整洁,分离性更加好
class Model(metaclass=BaseModel):
    def __init__(self, *args, **kwargs):
        for key, value in kwargs.items():
            if getattr(self, key, None):
                setattr(self, key, value)
def save(self): fields = [] values = [] for key, value in self.fields.items(): fields.append(key) values.append(str(getattr(self, key))) sql = "insert in into {db_table}({fields}) values{values}".format(db_table=self.db_table, fields=",".join(fields), values=",".join(values)) print(sql)

创建model

class User(Model):
    name = CharField(max_lenth=10, min_lenth=2)
    height = InField(max_lenth=300, min_lenth=50)

    class Meta:
        # 指明数据库中的数据表
        db_table = "用户"


if __name__ == "__main__":
    # user = User()
    # user.name = "witt"
    # user.height = 170
    user = User(name="witt", height=170)
    user.save()

这样就基本实现了一个orm

posted @ 2020-03-13 22:15  _WittChen  阅读(248)  评论(0)    收藏  举报