Python實現一個ORM模型類

ORM是三個單詞首字母組合而成,包含了Object(對象-類),Relations(關係),Mapping(映射)。解釋過字面意思,但ORM的概念仍然模糊。私覺得要理解一個事物,最好的法子是搞明白它出現是爲了解決什麼問題。sql

一個簡單的ORM模型

咱們也能夠經過元類來實現本身的ORM。下面將涉及兩個知識點:元類,描述符。app

首先完成屬性描述符的設計:

class BaseFiled(object):
    pass


class CharFiled(BaseFiled):
    def __init__(self, max_len=10):
        self.max_len = max_len

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

    def __set__(self, instance, value):
        if isinstance(value, str):
            # 判斷類型進行控制
            if len(value) <= self.max_len:
                self.value = value
            else:
                raise TypeError('超出最大長度')
        else:
            raise TypeError('need a str')

    def __delete__(self, instance):
        self.value = None


class IntFiled(BaseFiled):
    def __init__(self, max_len=10):
        self.max_len = max_len

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

    def __set__(self, instance, value):
        if isinstance(value, int):
            # 判斷類型進行控制
            if len(str(value)) <= self.max_len:
                self.value = value
            else:
                raise TypeError('超出最大長度')
        else:
            raise TypeError('need a int')

    def __delete__(self, instance):
        self.value = None


class BoolFiled(BaseFiled):
    def __init__(self, max_len=10):
        self.max_len = max_len

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

    def __set__(self, instance, value):
        if isinstance(value, bool):
            # 判斷類型進行控制
            self.value = value
        else:
            raise TypeError('need a bool')

實現一個元類:

class FieldMetaClass(type):
    # 建立模型類的元類
    def __new__(cls, name, bases, dic, *args, **kwargs):
        if name == 'BaseModel':
            return super().__new__(cls, name, bases, dic)
        table_name = name.lower()
        # 將類名轉換成小寫,對應數據表的名稱
        fields = {}
        for k, v in dic.items():
            # 判斷value的類型是否是BaseFiled類型的 由於調用的類的父類就是BaseFiled 因此經過CharFiled等建立出來的對象也就是BaseFiled類型的
            if isinstance(v, BaseFiled):
                fields[k] = v
        dic['t_name'] = table_name
        dic['fields'] = fields
        # 將類名和屬性取出來放在一個字典中
        return super().__new__(cls, name, bases, dic)

給模型類建立一個父類,具體緣由及做用能夠觀察註釋:

class BaseModel(metaclass=FieldMetaClass):
    # 模型類的父類
    def __init__(self, **kwargs):
        # kwargs 傳入的是一個字典
        for k, v in kwargs.items():
            setattr(self, k, v)
            # setattr 設置屬性  傳入對象、屬性名、屬性值

    def save(self):
        # 保存一條數據,生成一條對應的sql語句
        # 獲取表名
        t_name = self.t_name
        # 獲取字段名稱
        fields = self.fields
        # 獲取對應字段的值
        filed_dict = {} # 建立一個字典用來存儲鍵值對
        for filed in fields.keys():
            value = getattr(self, filed)
            # 把遍歷出來的鍵中的值找到
            filed_dict[filed] = value

        # 生成對應的sql語句
        sql = 'INSERT INTO {0} VALUES {1};'.format(t_name, tuple(filed_dict.values()))
       

生成模型類:

class User(BaseModel):
    # 用戶模型類 在模型類中不會重寫init方法,在它的父類中寫init方法 它會自動繼承
    username = CharFiled()
    pwd = CharFiled()
    age = IntFiled()
    live = BoolFiled()

調用方式:

a = User(username='12', pwd='19', age=20, live=True)
a.save()

這樣就實現了一個模型類,註釋寫的我的感受仍是比較清晰的,有不清楚的歡迎留言交流spa

相關文章
相關標籤/搜索