亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

用 Python 元類(lèi)的特性實(shí)現(xiàn) ORM 框架

瀏覽:3日期:2022-06-19 10:18:14
目錄ORM是什么實(shí)現(xiàn)ORM中的insert功能完善對(duì)數(shù)據(jù)類(lèi)型的檢測(cè)抽取到基類(lèi)中添加數(shù)據(jù)庫(kù)驅(qū)動(dòng)執(zhí)行sql語(yǔ)句添加數(shù)據(jù)庫(kù)驅(qū)動(dòng)執(zhí)行sql語(yǔ)句測(cè)試功能準(zhǔn)備數(shù)據(jù)庫(kù)創(chuàng)建模型類(lèi)測(cè)試源代碼ORM是什么

O是 object,也就 類(lèi)對(duì)象 的意思,R是 relation,翻譯成中文是 關(guān)系,也就是關(guān)系數(shù)據(jù)庫(kù)中 數(shù)據(jù)表 的意思,M是 mapping,是映射的意思。在ORM框架中,它幫我們把類(lèi)和數(shù)據(jù)表進(jìn)行了一個(gè)映射,可以讓我們通過(guò)類(lèi)和類(lèi)對(duì)象就能操作它所對(duì)應(yīng)的表格中的數(shù)據(jù)。ORM框架還有一個(gè)功能,它可以根據(jù)我們?cè)O(shè)計(jì)的類(lèi)自動(dòng)幫我們生成數(shù)據(jù)庫(kù)中的表,省去了我們自己建表的過(guò)程。

一個(gè)句話(huà)理解就是:創(chuàng)建一個(gè)實(shí)例對(duì)象,用創(chuàng)建它的類(lèi)名當(dāng)做數(shù)據(jù)表名,用創(chuàng)建它的類(lèi)屬性對(duì)應(yīng)數(shù)據(jù)表的字段,當(dāng)對(duì)這個(gè)實(shí)例對(duì)象操作時(shí),能夠?qū)?yīng) MySQL 語(yǔ)句。

在 Django 中就內(nèi)嵌了一個(gè) ORM 框架,不需要直接面向數(shù)據(jù)庫(kù)編程,而是定義模型類(lèi),通過(guò)模型類(lèi)和對(duì)象完成數(shù)據(jù)表的增刪改查操作。還有第三方庫(kù) sqlalchemy 都是 ORM框架。

用 Python 元類(lèi)的特性實(shí)現(xiàn) ORM 框架

先看看我們大致要實(shí)現(xiàn)什么功能

class User(父類(lèi)省略): uid = (’uid’, 'int unsigned') name = (’username’, 'varchar(30)') email = (’email’, 'varchar(30)') password = (’password’, 'varchar(30)') ...省略...user = User(uid=123, name=’hui’, email=’[email protected]’, password=’123456’)user.save()# 對(duì)應(yīng)如下sql語(yǔ)句# insert into User (uid,username,email,password) values (123,hui,[email protected],123456)

所謂的 ORM 就是讓開(kāi)發(fā)者在操作數(shù)據(jù)庫(kù)的時(shí)候,能夠像操作對(duì)象時(shí)通過(guò)xxxx.屬性=yyyy一樣簡(jiǎn)單,這是開(kāi)發(fā)ORM的初衷。

實(shí)現(xiàn)ORM中的insert功能

通過(guò) Python 中 元類(lèi) 簡(jiǎn)單實(shí)現(xiàn) ORM 中的 insert 功能

# !/usr/bin/python3# -*- coding: utf-8 -*-# @Author: Hui# @Desc: { 利用Python元類(lèi)簡(jiǎn)單實(shí)現(xiàn)ORM框架的Insert插入功能 }# @Date: 2021/05/17 17:02class ModelMetaclass(type): '''數(shù)據(jù)表模型元類(lèi)''' def __new__(mcs, cls_name, bases, attrs):print(f’cls_name -> {cls_name}’) # 類(lèi)名print(f’bases -> {bases}’) # 繼承類(lèi)print(f’attrs -> {attrs}’) # 類(lèi)中所有屬性print()# 數(shù)據(jù)表對(duì)應(yīng)關(guān)系字典mappings = dict()# 過(guò)濾出對(duì)應(yīng)數(shù)據(jù)表的字段屬性for k, v in attrs.items(): # 判斷是否是指定的StringField或者IntegerField的實(shí)例對(duì)象 # 這里就簡(jiǎn)單判斷字段是元組 if isinstance(v, tuple):print(’Found mapping: %s ==> %s’ % (k, v))mappings[k] = v# 刪除這些已經(jīng)在字典中存儲(chǔ)的字段屬性for k in mappings.keys(): attrs.pop(k)# 將之前的uid/name/email/password以及對(duì)應(yīng)的對(duì)象引用、類(lèi)名字# 用其他類(lèi)屬性名稱(chēng)保存attrs[’__mappings__’] = mappings # 保存屬性和列的映射關(guān)系attrs[’__table__’] = cls_name # 假設(shè)表名和類(lèi)名一致return type.__new__(mcs, cls_name, bases, attrs)class User(metaclass=ModelMetaclass): '''用戶(hù)模型類(lèi)'''# 類(lèi)屬性名 表字段 表字段類(lèi)型 uid = (’uid’, ’int unsigned’) name = (’username’, ’varchar(30)’) email = (’email’, ’varchar(30)’) password = (’password’, ’varchar(30)’) def __init__(self, **kwargs):for name, value in kwargs.items(): setattr(self, name, value) def save(self):fields = []args = []for k, v in self.__mappings__.items(): fields.append(v[0]) args.append(getattr(self, k, None))# 表名table_name = self.__table__# 數(shù)據(jù)表中的字段fields = ’,’.join(fields)# 待插入的數(shù)據(jù)args = ’,’.join([str(i) for i in args])# 生成sql語(yǔ)句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)def main(): user = User(uid=123, name=’hui’, email=’[email protected]’, password=’123456’) user.save()if __name__ == ’__main__’: main()

當(dāng) User 指定元類(lèi)之后,uid、name、email、password 類(lèi)屬性將不在類(lèi)中,而是在 __mappings__ 屬性指定的字典中存儲(chǔ)。 User 類(lèi)的這些屬性將轉(zhuǎn)變?yōu)槿缦?/p>

__mappings__ = { 'uid': (’uid’, 'int unsigned') 'name': (’username’, 'varchar(30)') 'email': (’email’, 'varchar(30)') 'password': (’password’, 'varchar(30)')}__table__ = 'User'

執(zhí)行的效果如下:

cls_name -> Userbases -> ()attrs -> { ’__module__’: ’__main__’, ’__qualname__’: ’User’, ’__doc__’: ’用戶(hù)模型類(lèi)’, ’uid’: (’uid’, ’int unsigned’), ’name’: (’username’, ’varchar(30)’), ’email’: (’email’, ’varchar(30)’), ’password’: (’password’, ’varchar(30)’), ’__init__’: <function User.__init__ at 0x0000026D520C1048>, ’save’: <function User.save at 0x0000026D520C10D8>}Found mapping: uid ==> (’uid’, ’int unsigned’)Found mapping: name ==> (’username’, ’varchar(30)’)Found mapping: email ==> (’email’, ’varchar(30)’)Found mapping: password ==> (’password’, ’varchar(30)’)SQL: insert into User (uid,username,email,password) values (123,hui,[email protected],123456)完善對(duì)數(shù)據(jù)類(lèi)型的檢測(cè)

上面轉(zhuǎn)成的 sql 語(yǔ)句如下:

insert into User (uid,username,email,password) values (12345,hui,[email protected],123456)

發(fā)現(xiàn)沒(méi)有,在 sql 語(yǔ)句中字符串類(lèi)型沒(méi)有沒(méi)有引號(hào) ’’

正確的 sql 語(yǔ)句應(yīng)該是:

insert into User (uid,username,email,password) values (123, ’hui’, ’[email protected]’, ’123456’)

因此修改 User 類(lèi)完善數(shù)據(jù)類(lèi)型的檢測(cè)

class ModelMetaclass(type): # 此處和上文一樣, 故省略.... pass class User(metaclass=ModelMetaclass): '''用戶(hù)模型類(lèi)''' uid = (’uid’, 'int unsigned') name = (’username’, 'varchar(30)') email = (’email’, 'varchar(30)') password = (’password’, 'varchar(30)') def __init__(self, **kwargs):for name, value in kwargs.items(): setattr(self, name, value) # 在這里完善數(shù)據(jù)類(lèi)型檢測(cè) def save(self):fields = []args = []for k, v in self.__mappings__.items(): fields.append(v[0]) args.append(getattr(self, k, None))# 把參數(shù)數(shù)據(jù)類(lèi)型對(duì)應(yīng)數(shù)據(jù)表的字段類(lèi)型args_temp = list()for temp in args: if isinstance(temp, int):args_temp.append(str(temp)) elif isinstance(temp, str):args_temp.append(f'’{temp}’')# 表名table_name = self.__table__# 數(shù)據(jù)表中的字段fields = ’,’.join(fields)# 待插入的數(shù)據(jù)args = ’,’.join(args_temp)# 生成sql語(yǔ)句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)def main(): user = User(uid=123, name=’hui’, email=’[email protected]’, password=’123456’) user.save()if __name__ == ’__main__’: main()

運(yùn)行效果如下:

cls_name -> Userbases -> ()attrs -> { ’__module__’: ’__main__’, ’__qualname__’: ’User’, ’__doc__’: ’用戶(hù)模型類(lèi)’, ’uid’: (’uid’, ’int unsigned’), ’name’: (’username’, ’varchar(30)’), ’email’: (’email’, ’varchar(30)’), ’password’: (’password’, ’varchar(30)’), ’__init__’: <function User.__init__ at 0x0000026D520C1048>, ’save’: <function User.save at 0x0000026D520C10D8>}Found mapping: uid ==> (’uid’, ’int unsigned’)Found mapping: name ==> (’username’, ’varchar(30)’)Found mapping: email ==> (’email’, ’varchar(30)’)Found mapping: password ==> (’password’, ’varchar(30)’) SQL: insert into User (uid,username,email,password) values(123,’hui’,’[email protected]’,’123456’)抽取到基類(lèi)中

# !/usr/bin/python3# -*- coding: utf-8 -*-# @Author: Hui# @Desc: { 利用Python元類(lèi)實(shí)現(xiàn)ORM框架的Insert插入功能 }# @Date: 2021/05/17 17:02class ModelMetaclass(type): '''數(shù)據(jù)表模型元類(lèi)''' def __new__(mcs, cls_name, bases, attrs):print(f’cls_name -> {cls_name}’) # 類(lèi)名print(f’bases -> {bases}’) # 繼承類(lèi)print(f’attrs -> {attrs}’) # 類(lèi)中所有屬性print()# 數(shù)據(jù)表對(duì)應(yīng)關(guān)系字典mappings = dict()# 過(guò)濾出對(duì)應(yīng)數(shù)據(jù)表的字段屬性for k, v in attrs.items(): # 判斷是否是對(duì)應(yīng)數(shù)據(jù)表的字段屬性, 因?yàn)閍ttrs中包含所有的類(lèi)屬性 # 這里就簡(jiǎn)單判斷字段是元組 if isinstance(v, tuple):print(’Found mapping: %s ==> %s’ % (k, v))mappings[k] = v# 刪除這些已經(jīng)在字典中存儲(chǔ)的字段屬性for k in mappings.keys(): attrs.pop(k)# 將之前的uid/name/email/password以及對(duì)應(yīng)的對(duì)象引用、類(lèi)名字# 用其他類(lèi)屬性名稱(chēng)保存attrs[’__mappings__’] = mappings # 保存屬性和列的映射關(guān)系attrs[’__table__’] = cls_name # 假設(shè)表名和類(lèi)名一致return type.__new__(mcs, cls_name, bases, attrs)class Model(object, metaclass=ModelMetaclass): '''數(shù)據(jù)表模型基類(lèi)''' def __init__(self, **kwargs):for name, value in kwargs.items(): setattr(self, name, value) def save(self):fields = []args = []for k, v in self.__mappings__.items(): fields.append(v[0]) args.append(getattr(self, k, None))# 把參數(shù)數(shù)據(jù)類(lèi)型對(duì)應(yīng)數(shù)據(jù)表的字段類(lèi)型args_temp = list()for temp in args: if isinstance(temp, int):args_temp.append(str(temp)) elif isinstance(temp, str):args_temp.append(f'’{temp}’')# 表名table_name = self.__table__# 數(shù)據(jù)表中的字段fields = ’,’.join(fields)# 待插入的數(shù)據(jù)args = ’,’.join(args_temp)# 生成sql語(yǔ)句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)# 執(zhí)行sql語(yǔ)句# ...class User(Model): '''用戶(hù)表模型類(lèi)''' uid = (’uid’, 'int unsigned') name = (’username’, 'varchar(30)') email = (’email’, 'varchar(30)') password = (’password’, 'varchar(30)')def main(): user = User(uid=123, name=’hui’, email=’[email protected]’, password=’123456’) user.save()if __name__ == ’__main__’: main()添加數(shù)據(jù)庫(kù)驅(qū)動(dòng)執(zhí)行sql語(yǔ)句

這里我們使用 pymysql 數(shù)據(jù)庫(kù)驅(qū)動(dòng),來(lái)執(zhí)行 sql 語(yǔ)句

在 Model 類(lèi)中新增一個(gè) get_connection 的靜態(tài)方法用于獲取數(shù)據(jù)庫(kù)連接

import pymysqlclass Model(object, metaclass=ModelMetaclass): '''數(shù)據(jù)表模型基類(lèi)''' def __init__(self, **kwargs):for name, value in kwargs.items(): setattr(self, name, value) @staticmethod def get_connection():'''獲取數(shù)據(jù)庫(kù)連接與數(shù)據(jù)游標(biāo):return: conn, cursor'''conn = pymysql.connect( database=’testdb’, host=’localhost’, port=3306, user=’root’, password=’123456’)return conn, conn.cursor() def save(self):fields = []args = []for k, v in self.__mappings__.items(): fields.append(v[0]) args.append(getattr(self, k, None))# 把參數(shù)數(shù)據(jù)類(lèi)型對(duì)應(yīng)數(shù)據(jù)表的字段類(lèi)型args_temp = list()for temp in args: if isinstance(temp, int):args_temp.append(str(temp)) elif isinstance(temp, str):args_temp.append(f'’{temp}’')# 表名table_name = self.__table__# 數(shù)據(jù)表中的字段fields = ’,’.join(fields)# 待插入的數(shù)據(jù)args = ’,’.join(args_temp)# 生成sql語(yǔ)句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)# 執(zhí)行sql語(yǔ)句conn, cursor = self.get_connection()ret = cursor.execute(sql)print(ret)conn.commit()cursor.close()conn.close()添加數(shù)據(jù)庫(kù)驅(qū)動(dòng)執(zhí)行sql語(yǔ)句

這里我們使用 pymysql 數(shù)據(jù)庫(kù)驅(qū)動(dòng),來(lái)執(zhí)行 sql 語(yǔ)句

在 Model 類(lèi)中新增一個(gè) get_connection 的靜態(tài)方法用于獲取數(shù)據(jù)庫(kù)連接

import pymysqlclass Model(object, metaclass=ModelMetaclass): '''數(shù)據(jù)表模型基類(lèi)''' def __init__(self, **kwargs):for name, value in kwargs.items(): setattr(self, name, value) @staticmethod def get_connection():'''獲取數(shù)據(jù)庫(kù)連接與數(shù)據(jù)游標(biāo):return: conn, cursor'''conn = pymysql.connect( database=’testdb’, host=’localhost’, port=3306, user=’root’, password=’123456’)return conn, conn.cursor() def save(self):fields = []args = []for k, v in self.__mappings__.items(): fields.append(v[0]) args.append(getattr(self, k, None))# 把參數(shù)數(shù)據(jù)類(lèi)型對(duì)應(yīng)數(shù)據(jù)表的字段類(lèi)型args_temp = list()for temp in args: if isinstance(temp, int):args_temp.append(str(temp)) elif isinstance(temp, str):args_temp.append(f'’{temp}’')# 表名table_name = self.__table__# 數(shù)據(jù)表中的字段fields = ’,’.join(fields)# 待插入的數(shù)據(jù)args = ’,’.join(args_temp)# 生成sql語(yǔ)句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)# 執(zhí)行sql語(yǔ)句conn, cursor = self.get_connection()ret = cursor.execute(sql)print(ret)conn.commit()cursor.close()conn.close()測(cè)試功能準(zhǔn)備數(shù)據(jù)庫(kù)

先準(zhǔn)備數(shù)據(jù)庫(kù) testdb 和 user 數(shù)據(jù)表

create database testdb charset=utf8;use testdb;create table user(uid int unsigned auto_increment primary key,username varchar(30) not null,email varchar(30),password varchar(30) not null);

user 表結(jié)構(gòu)如下

+----------+------------------+------+-----+---------+----------------+| Field | Type | Null | Key | Default | Extra |+----------+------------------+------+-----+---------+----------------+| uid | int(10) unsigned | NO | PRI | NULL | auto_increment || username | varchar(30) | NO | | NULL ||| email | varchar(30) | YES | | NULL ||| password | varchar(30) | NO | | NULL ||+----------+------------------+------+-----+---------+----------------+創(chuàng)建模型類(lèi)測(cè)試

class User(Model): '''用戶(hù)表模型類(lèi)''' uid = (’uid’, 'int unsigned') name = (’username’, 'varchar(30)') email = (’email’, 'varchar(30)') password = (’password’, 'varchar(30)')def main(): user = User(uid=1, name=’hui’, email=’[email protected]’, password=’123456’) user.save() for i in range(2, 10):user = User( uid=i, name=f’name{i}’, email=f’huidbk@16{i}.com’, password=f’12345{i}’)user.save() if __name__ == ’__main__’: main()

查看數(shù)據(jù)庫(kù) user 表數(shù)據(jù)

mysql> select * from user;+-----+----------+----------------+----------+| uid | username | email | password |+-----+----------+----------------+----------+| 1 | hui | [email protected] | 123456 || 2 | name2 | [email protected] | 123452 || 3 | name3 | [email protected] | 123453 || 4 | name4 | [email protected] | 123454 || 5 | name5 | [email protected] | 123455 || 6 | name6 | [email protected] | 123456 || 7 | name7 | [email protected] | 123457 || 8 | name8 | [email protected] | 123458 || 9 | name9 | [email protected] | 123459 |+-----+----------+----------------+----------+9 rows in set (0.00 sec)源代碼

源代碼已上傳到 Gitee PythonKnowledge: Python知識(shí)寶庫(kù),歡迎大家來(lái)訪。

以上就是用 Python 元類(lèi)的特性實(shí)現(xiàn) ORM 框架的詳細(xì)內(nèi)容,更多關(guān)于Python 實(shí)現(xiàn) ORM 框架的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 日本一级特黄大一片免 | 国产精品久久久久久久久鸭 | 国产精品伊人 | 丁香月婷婷| 亚洲国产经典 | 国产不卡一卡2卡三卡4卡5卡在线 | 黄网在线免费 | 日本久久网站 | 精品日韩欧美一区二区三区 | 手机看片日韩国产福利视频 | 久久国产精品免费一区二区三区 | 色综合合久久天天综合绕视看 | 亚洲第一毛片 | 国产精品www视频免费看 | 国产精品思瑞在线观看 | 久久线看观看精品香蕉国产 | 国产羞羞视频 | 搜索黄色毛片 | 国产羞羞事1000部在线观看 | 国产老肥妇视频 | 久久精彩免费视频 | 亚洲精品一区二区三区四区 | 亚洲福利片 | 欧美黄色毛片 | 久久国产精品-国产精品 | 欧美中文字幕第一页 | 国产色综合天天综合网 | 国内精品久久久久久 | 免费播放国产性色生活片 | 国产精品亚洲精品影院 | 韩国主播vip福利视频在线播放 | 香蕉视频黄色 | 黑人狂躁日本妞 | 国产精品视频免费一区二区三区 | 国产精品一区视频 | 日本在线精品视频 | 久久久久久九九 | 久久久久激情免费观看 | 放几个免费的毛片出来看 | 制服丝袜日韩欧美 | 久久国产亚洲欧美日韩精品 |