ORM是三個單詞首字母組合而成,包含了Object(對象-類),Relations(關係),Mapping(映射)。解釋過字面意思,但ORM的概念仍然模糊。私覺得要理解一個事物,最好的法子是搞明白它出現是爲了解決什麼問題。sql
咱們也能夠經過元類來實現本身的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