python自定義ORM並操作數據庫


看這個代碼之前先去看上篇文章,理解type的用法及元類的含義:

ORM可以代替pymysql,實現將python語義裝換為sql語句,簡單化

    import pymysql
    ''' metaclass,直譯為元類,簡單的解釋就是: 當我們定義了類以后,就可以根據這個類創建出實例,所以:先定義類,然后創建實例。 但是如果我們想創建出類呢?那就必須根據metaclass創建出類,所以:先定義metaclass,然后創建類。 連接起來就是:先定義metaclass,就可以創建類,最后創建實例。 所以,metaclass允許你創建類或者修改類。換句話說,你可以把類看成是metaclass創建出來的“實例”。 當我們傳入關鍵字參數metaclass時,魔術就生效了,它指示Python解釋器在創建Student時, 要通過ModelMetaClass.__new__()來創建,在此,我們可以修改類的定義,比如,加上新的方法,然后,返回修改后的定義。 '''
    class Field(object):#定義一個字段類
        def __init__(self,name,column_type):
            self.name = name#字段名
            self.column_type = column_type#字段類型
        def __str__(self):
            return "<%s:%s>"%(self.name,self.column_type)
    
    class StringField(Field):#字符串類型字段,繼承Field
        def __init__(self,name):
            super(StringField,self).__init__(name,"varchar(100)")
            # super(StringField, self).__init__(name,char(20))
    
    class IntegerField(Field):#數字類型字段,繼承Field
        def __init__(self,name):
            super(IntegerField,self).__init__(name,"int")
    
    class ModelMetaClass(type):#定義一個元類
        def __new__(cls, name,bases,attrs):
            ''' :param name: 類的名稱 :param bases: 類的繼承 :param attrs: 類的屬性 :return: '''
            if name == "Model":#如果傳入的name:類名為Model則不進行操作,直接返回type類的相關參數
                return type.__new__(cls,name,bases,attrs)
                # return super(ModelMetaClass, self).__new__(cls,name,bases,attrs)
            print('Found model: %s' % name)  # 打印當前實例的類名稱
            mapping = dict() #空字典
            for k,v in attrs.items(): #遍歷屬性
                print('key:%s,value:%s' % (k, v))#打印遍歷attrs的key和value
                if isinstance(v,Field): #判斷屬性是否Field的實例
                    mapping[k] = v #添加到mapping當中
            # print(mapping)
            for k in mapping.keys(): #返回所有鍵
                attrs.pop(k) #mapping里存在的內容從屬性當中刪除
            attrs["__mapping__"] = mapping  #設定__mapping__屬性來保存字段
            attrs["__table__"] = name #設定類名和表名一致(不區分大小寫)
            # print(attrs)
            return type.__new__(cls,name,bases,attrs)#返回給類實例,這里為Student
    
    class Model(dict,metaclass = ModelMetaClass):#創建一個實例類,設置其元類
        def __init__(self,**kwargs):
            self.db = pymysql.connect(#鏈接數據庫
                host = "localhost",
                user = "root",
                password = "123",
                database = "test"
            )
            self.cursor = self.db.cursor()
            super(Model,self).__init__(**kwargs)
    
        def __getattr__(self, key):
            return self[key]#返回對象的屬性值
            # print(self[key])
        def __setattr__(self, key, value):
            self[key] = value#設置對象的屬性及其對應的值
    
    
        def save(self):
            fields = [] #空列表用來存儲字段
            args = [] #空列表用來存儲字段的值
            for k,v in self.__mapping__.items():
                fields.append(v.name)#此時,v為field子類的實例,因此可以取出類屬性name,作為字段名
                # print(getattr(self, k, None))
                args.append(getattr(self,k,None))#此時調用了self,則將傳入的參數調用,此時再取變量的值,則為傳入的實參
            sql = "insert into %s(%s) values (%s)"%(
                self.__table__,
                ",".join(fields),
                ",".join([repr(str(i)) for i in args]
                   )) #sql拼接
            self.cursor.execute(sql)
            print(sql)
        def __del__(self):
            ''' 回收內存 '''
            self.db.commit()
            self.cursor.close()
            self.db.close()
    
    class Student(Model):#model實例類的子類
        name = StringField("name")
        # print(name)
        room_id = IntegerField("room_id")
        # print(room_id)
    
    u = Student(name = "張3",room_id = 6)#實質是創建了一個字典的對象
    u.save()#調用父類的save方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM