91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么使用Python元類編程實現一個簡單的ORM

發布時間:2023-03-07 14:54:27 來源:億速云 閱讀:268 作者:iii 欄目:開發技術

這篇文章主要講解了“怎么使用Python元類編程實現一個簡單的ORM”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么使用Python元類編程實現一個簡單的ORM”吧!

概述

什么是ORM?   

ORM全稱“Object Relational Mapping”,即對象-關系映射,就是把關系數據庫的一行映射為一個對象,也就是一個類對應一個表,這樣,寫代碼更簡單,不用直接操作SQL語句。

現在我們就要實現簡易版ORM。 

效果

class Person(Model):
    """
    定義類的屬性到列的映射
    """
    pid = IntegerField('id')
    names = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
p = Person(pid=10086, names='曉明', email='10086@163.com', password='123456')
p.save()

怎么使用Python元類編程實現一個簡單的ORM

通過執行save()方法 動態生成sql插入語句, 是不是很神奇, 那我們現在開始解析原理吧

步驟

首先我們要定義一個 Field 類 它負責保存數據庫表的字段名和字段類型:

class Field(object):
    def __init__(self, name, column_type):
        self.name = name
        self.column_type = column_type
    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)

在 Field 的基礎上,進一步定義各種類型的 Field,比如 StringField,IntegerField 等等:

class StringField(Field):
    def __init__(self, name):
        super(StringField, self).__init__(name, 'varchar(100)')
 
class IntegerField(Field):
    def __init__(self, name):
        super(IntegerField, self).__init__(name, 'bigint')

下一步,就是編寫最復雜的 ModelMetaclass:

class ModelMetaclass(type):
 
    def __new__(cls, name, bases, attrs):
        if name == "Model":
            return type.__new__(cls, name, bases, attrs)
        mappings = dict()
        print("Found class: %s" % name)
        for k, v in attrs.items():
            if isinstance(v, Field):
                print("Found mapping: %s ==> %s" % (k, v))
                mappings[k] = v
        for k in mappings.keys():
            attrs.pop(k)
        attrs["__table__"] = name  # 表名和類名一致
        attrs["__mappings__"] = mappings  # 保存屬性和列的映射關系
        return type.__new__(cls, name, bases, attrs)

最后就是基類  Model:

class Model(metaclass=ModelMetaclass):
 
    def __init__(self, **kwargs):
        _setattr = setattr
        if kwargs:
            for k, v in kwargs.items():
                _setattr(self, k, v)
        super(Model, self).__init__()
 
    def save(self):
        fields = []
        params = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(k)
            params.append("?")
            args.append(getattr(self, k, None))
        sql = "insert into %s (%s) values (%s)" % (self.__table__, ','.join(fields), ",".join(params))
        print('插入語句: %s' % sql)
        print('參數: %s' % str(args))
 
    def update(self):
        fields = []
        args = []
        for k, v in self.__mappings__.items():
            if getattr(self, k, None):
                fields.append(k+"=?")
                args.append(getattr(self, k, None))
        sql = "update %s set %s" % (self.__table__, ','.join(fields))
        print("更新語句: %s " % sql)
        print("參數: %s" % args)
 
    def filter(self, *args):
        pass
 
    def delete(self):
        pass

當用戶定義一個 class Person(Model) 繼承父類時,Python解釋器會在當前類 Person 的定義中找 __metaclass__,如果沒有找到,就繼續到父類中找 __metaclass__,實在找不到就用默認 type 類。

我們在父類 Model 中定義了 __metaclass__ 的 ModelMetaclass 來創建 Person 類,所以 metaclass 隱式地繼承到子類。

在 ModelMetaclass 中,一共做了幾件事情:

  • 排除掉對 Model 類的修改;

  • 在當前類(比如 Person )中查找定義的類的所有屬性,如果找到一個 Field 屬性,就把它保存到一個 __mappings__ 的dict中,同時從類屬性中刪除該Field屬性,否則,容易造成運行時錯誤;

  • 把表名保存到 __table__ 中,這里簡化為表名默認為類名。

在Model類中,就可以定義各種操作數據庫的方法,比如save(),delete(),find(),update() 等等。

我們實現了save(), update()方法,把一個實例保存到數據庫中。因為有表名,屬性到字段的映射和屬性值的集合,就可以構造出INSERT語句和UPDATE語句。

編寫代碼試試:

class UserInfo(Model):
    """
        定義類的屬性到列的映射
    """
    uid = IntegerField('uid')
    name = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
 
class Person(Model):
    """
    定義類的屬性到列的映射
    """
    pid = IntegerField('id')
    names = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
p = Person(pid=10086, names='曉明', email='10086@163.com', password='123456')
p.save()
u2 = UserInfo(password='123456')
u2.update()

輸出

Found class: UserInfo
Found mapping: uid ==> <IntegerField:uid>
Found mapping: name ==> <StringField:username>
Found mapping: email ==> <StringField:email>
Found mapping: password ==> <StringField:password>
Found class: Person
Found mapping: pid ==> <IntegerField:id>
Found mapping: names ==> <StringField:username>
Found mapping: email ==> <StringField:email>
Found mapping: password ==> <StringField:password>
插入語句: insert into Person (pid,names,email,password) values (?,?,?,?)
參數: [10086, '曉明', '10086@163.com', '123456']
更新語句: update UserInfo set password=? 
參數: ['123456']

結束語

就這樣一個小巧的ORM就這么完成了。是不是學到了很多呢 ?這里利用的是元編程,很多Python框架都運用了元編程達到動態操作類。

注:上述代碼列子 結合了廖雪峰的列子和少量的django ORM源碼。

完整代碼

class Field(object):
    def __init__(self, name, column_type):
        self.name = name
        self.column_type = column_type
 
    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)
 
 
class StringField(Field):
    def __init__(self, name):
        super(StringField, self).__init__(name, 'varchar(100)')
 
 
class IntegerField(Field):
    def __init__(self, name):
        super(IntegerField, self).__init__(name, 'bigint')
 
 
class ModelMetaclass(type):
 
    def __new__(cls, name, bases, attrs):
        if name == "Model":
            return type.__new__(cls, name, bases, attrs)
        mappings = dict()
        print("Found class: %s" % name)
        for k, v in attrs.items():
            if isinstance(v, Field):
                print("Found mapping: %s ==> %s" % (k, v))
                mappings[k] = v
        for k in mappings.keys():
            attrs.pop(k)
        attrs["__table__"] = name  # 表名和類名一致
        attrs["__mappings__"] = mappings  # 保存屬性和列的映射關系
        return type.__new__(cls, name, bases, attrs)
 
 
class Model(metaclass=ModelMetaclass):
 
    def __init__(self, **kwargs):
        _setattr = setattr
        if kwargs:
            for k, v in kwargs.items():
                _setattr(self, k, v)
        super(Model, self).__init__()
 
    def save(self):
        fields = []
        params = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(k)
            params.append("?")
            args.append(getattr(self, k, None))
        sql = "insert into %s (%s) values (%s)" % (self.__table__, ','.join(fields), ",".join(params))
        print('插入語句: %s' % sql)
        print('參數: %s' % str(args))
 
    def update(self):
        fields = []
        args = []
        for k, v in self.__mappings__.items():
            if getattr(self, k, None):
                fields.append(k+"=?")
                args.append(getattr(self, k, None))
        sql = "update %s set %s" % (self.__table__, ','.join(fields))
        print("更新語句: %s " % sql)
        print("參數: %s" % args)
 
    def filter(self, *args):
        pass
 
    def delete(self):
        pass
 
 
class UserInfo(Model):
    """
        定義類的屬性到列的映射
    """
    uid = IntegerField('uid')
    name = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
 
class Person(Model):
    """
    定義類的屬性到列的映射
    """
    pid = IntegerField('id')
    names = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
p = Person(pid=10086, names='曉明', email='10086@163.com', password='123456')
p.save()
u2 = UserInfo(password='123456')
u2.update()

感謝各位的閱讀,以上就是“怎么使用Python元類編程實現一個簡單的ORM”的內容了,經過本文的學習后,相信大家對怎么使用Python元類編程實現一個簡單的ORM這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

海南省| 高台县| 宁武县| 龙岩市| 始兴县| 梨树县| 华阴市| 茶陵县| 北川| 蒙城县| 哈巴河县| 昭平县| 营山县| 健康| 和林格尔县| 岳普湖县| 南丰县| 丘北县| 海淀区| 新乡县| 青岛市| 梧州市| 罗山县| 达孜县| 乌兰县| 金秀| 梓潼县| 莒南县| 黑龙江省| 遵化市| 古蔺县| 吉首市| 沁水县| 渭南市| 郎溪县| 和田市| 利津县| 麟游县| 电白县| 苏州市| 博湖县|