成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

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

用 Python 元類的特性實現(xiàn) ORM 框架

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

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

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

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

用 Python 元類的特性實現(xiàn) ORM 框架

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

class User(父類省略): uid = (’uid’, 'int unsigned') name = (’username’, 'varchar(30)') email = (’email’, 'varchar(30)') password = (’password’, 'varchar(30)') ...省略...user = User(uid=123, name=’hui’, email=’huidbk@163.com’, password=’123456’)user.save()# 對應(yīng)如下sql語句# insert into User (uid,username,email,password) values (123,hui,huidbk@163.com,123456)

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

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

通過 Python 中 元類 簡單實現(xiàn) ORM 中的 insert 功能

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

當(dāng) User 指定元類之后,uid、name、email、password 類屬性將不在類中,而是在 __mappings__ 屬性指定的字典中存儲。 User 類的這些屬性將轉(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__’: ’用戶模型類’, ’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,huidbk@163.com,123456)完善對數(shù)據(jù)類型的檢測

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

insert into User (uid,username,email,password) values (12345,hui,huidbk@163.com,123456)

發(fā)現(xiàn)沒有,在 sql 語句中字符串類型沒有沒有引號 ’’

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

insert into User (uid,username,email,password) values (123, ’hui’, ’huidbk@163.com’, ’123456’)

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

class ModelMetaclass(type): # 此處和上文一樣, 故省略.... pass class User(metaclass=ModelMetaclass): '''用戶模型類''' 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ù)類型檢測 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ù)類型對應(yīng)數(shù)據(jù)表的字段類型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語句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)def main(): user = User(uid=123, name=’hui’, email=’huidbk@163.com’, password=’123456’) user.save()if __name__ == ’__main__’: main()

運行效果如下:

cls_name -> Userbases -> ()attrs -> { ’__module__’: ’__main__’, ’__qualname__’: ’User’, ’__doc__’: ’用戶模型類’, ’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’,’huidbk@163.com’,’123456’)抽取到基類中

# !/usr/bin/python3# -*- coding: utf-8 -*-# @Author: Hui# @Desc: { 利用Python元類實現(xiàn)ORM框架的Insert插入功能 }# @Date: 2021/05/17 17:02class ModelMetaclass(type): '''數(shù)據(jù)表模型元類''' def __new__(mcs, cls_name, bases, attrs):print(f’cls_name -> {cls_name}’) # 類名print(f’bases -> {bases}’) # 繼承類print(f’attrs -> {attrs}’) # 類中所有屬性print()# 數(shù)據(jù)表對應(yīng)關(guān)系字典mappings = dict()# 過濾出對應(yīng)數(shù)據(jù)表的字段屬性for k, v in attrs.items(): # 判斷是否是對應(yīng)數(shù)據(jù)表的字段屬性, 因為attrs中包含所有的類屬性 # 這里就簡單判斷字段是元組 if isinstance(v, tuple):print(’Found mapping: %s ==> %s’ % (k, v))mappings[k] = v# 刪除這些已經(jīng)在字典中存儲的字段屬性for k in mappings.keys(): attrs.pop(k)# 將之前的uid/name/email/password以及對應(yīng)的對象引用、類名字# 用其他類屬性名稱保存attrs[’__mappings__’] = mappings # 保存屬性和列的映射關(guān)系attrs[’__table__’] = cls_name # 假設(shè)表名和類名一致return type.__new__(mcs, cls_name, bases, attrs)class Model(object, metaclass=ModelMetaclass): '''數(shù)據(jù)表模型基類''' 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ù)類型對應(yīng)數(shù)據(jù)表的字段類型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語句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)# 執(zhí)行sql語句# ...class User(Model): '''用戶表模型類''' 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=’huidbk@163.com’, password=’123456’) user.save()if __name__ == ’__main__’: main()添加數(shù)據(jù)庫驅(qū)動執(zhí)行sql語句

這里我們使用 pymysql 數(shù)據(jù)庫驅(qū)動,來執(zhí)行 sql 語句

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

import pymysqlclass Model(object, metaclass=ModelMetaclass): '''數(shù)據(jù)表模型基類''' def __init__(self, **kwargs):for name, value in kwargs.items(): setattr(self, name, value) @staticmethod def get_connection():'''獲取數(shù)據(jù)庫連接與數(shù)據(jù)游標: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ù)類型對應(yīng)數(shù)據(jù)表的字段類型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語句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)# 執(zhí)行sql語句conn, cursor = self.get_connection()ret = cursor.execute(sql)print(ret)conn.commit()cursor.close()conn.close()添加數(shù)據(jù)庫驅(qū)動執(zhí)行sql語句

這里我們使用 pymysql 數(shù)據(jù)庫驅(qū)動,來執(zhí)行 sql 語句

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

import pymysqlclass Model(object, metaclass=ModelMetaclass): '''數(shù)據(jù)表模型基類''' def __init__(self, **kwargs):for name, value in kwargs.items(): setattr(self, name, value) @staticmethod def get_connection():'''獲取數(shù)據(jù)庫連接與數(shù)據(jù)游標: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ù)類型對應(yīng)數(shù)據(jù)表的字段類型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語句sql = f'''insert into {table_name} ({fields}) values ({args})'''print(f’SQL: {sql}’)# 執(zhí)行sql語句conn, cursor = self.get_connection()ret = cursor.execute(sql)print(ret)conn.commit()cursor.close()conn.close()測試功能準備數(shù)據(jù)庫

先準備數(shù)據(jù)庫 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)建模型類測試

class User(Model): '''用戶表模型類''' 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=’huidbk@163.com’, 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ù)庫 user 表數(shù)據(jù)

mysql> select * from user;+-----+----------+----------------+----------+| uid | username | email | password |+-----+----------+----------------+----------+| 1 | hui | huidbk@163.com | 123456 || 2 | name2 | huidbk@162.com | 123452 || 3 | name3 | huidbk@163.com | 123453 || 4 | name4 | huidbk@164.com | 123454 || 5 | name5 | huidbk@165.com | 123455 || 6 | name6 | huidbk@166.com | 123456 || 7 | name7 | huidbk@167.com | 123457 || 8 | name8 | huidbk@168.com | 123458 || 9 | name9 | huidbk@169.com | 123459 |+-----+----------+----------------+----------+9 rows in set (0.00 sec)源代碼

源代碼已上傳到 Gitee PythonKnowledge: Python知識寶庫,歡迎大家來訪。

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

標簽: Python 編程
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
精品影院一区二区久久久| 欧美一区二区大片| 欧美三级日韩在线| 18成人在线观看| 99久久精品国产毛片| 欧美日韩不卡在线| 亚洲午夜私人影院| 欧美日韩综合| 久久亚洲免费视频| 波多野结衣中文字幕一区二区三区| 欧美视频在线观看一区二区| 午夜影院在线观看欧美| 一道本一区二区| 成人免费一区二区三区在线观看| 激情欧美日韩一区二区| 一本到不卡精品视频在线观看 | 一本色道久久综合亚洲精品婷婷| 久久久久青草大香线综合精品| 国产91精品久久久久久久网曝门| 欧美日韩情趣电影| 免费观看成人鲁鲁鲁鲁鲁视频| 久久久福利视频| 午夜精品视频在线观看| 久久国产99| 亚洲国产成人va在线观看天堂| 99综合在线| 亚洲免费高清视频在线| 中国成人在线视频| 亚洲一区免费视频| 免费在线观看成人av| 亚洲成a人v欧美综合天堂| 亚洲一区二区三区免费观看| 亚洲小说欧美激情另类| 色悠悠亚洲一区二区| 午夜欧美一区二区三区在线播放| 久久国产日韩| 麻豆国产精品官网| 欧美久久久久久久久| 国产一区二区在线看| 日韩欧美美女一区二区三区| 成人午夜电影久久影院| 精品粉嫩超白一线天av| 99精品偷自拍| 欧美国产禁国产网站cc| 亚洲精品欧洲精品| 香蕉久久夜色精品国产使用方法 | 日韩欧美久久久| 日韩黄色免费电影| 久久亚洲精品欧美| 黄色小说综合网站| 欧美videossexotv100| 91偷拍与自偷拍精品| 国产精品久久久久精k8| 亚洲精品乱码| 日韩精品午夜视频| 91精品视频网| 国产成人午夜99999| 久久麻豆一区二区| 尹人成人综合网| 亚洲国产欧美日韩另类综合 | 色综合久久九月婷婷色综合| 天堂一区二区在线免费观看| 欧美午夜寂寞影院| 成人激情文学综合网| 亚洲欧美综合另类在线卡通| 亚洲一区在线免费| 激情五月婷婷综合网| 精品成人一区二区三区四区| 红桃视频欧美| 天天综合天天做天天综合| 欧美日韩一级大片网址| 国产成人综合网站| 日本一区二区免费在线观看视频| 亚洲激情自拍| 日韩成人免费电影| 精品国产乱码久久久久久夜甘婷婷| 欧美激情1区| 亚洲国产精品久久久男人的天堂| 欧美性猛片xxxx免费看久爱| 93久久精品日日躁夜夜躁欧美| 亚洲精品五月天| 欧美体内she精高潮| 91亚洲国产成人精品一区二三| 亚洲精品视频在线观看网站| 色88888久久久久久影院按摩| 夫妻av一区二区| 亚洲欧美激情一区二区| 欧美日韩三级在线| 狠狠色噜噜狠狠色综合久| 美女一区二区三区| 久久久久久久久久久久久久久99 | 欧美日韩第一区日日骚| 97精品电影院| 亚洲妇女屁股眼交7| 日韩一级大片在线观看| 亚洲黄色高清| 国产一区视频在线看| |精品福利一区二区三区| 欧美日韩在线不卡| 亚洲成人免费在线观看| 日韩欧美国产一区二区在线播放 | 欧美日韩综合不卡| 欧美在线亚洲| 天天操天天综合网| 精品国产免费一区二区三区四区| 国产亚洲网站| 成人黄色大片在线观看| 亚洲成人综合网站| 欧美tickle裸体挠脚心vk| 国产乱人伦精品一区二区| 国产91精品免费| 一区二区三区在线免费播放| 日韩一区二区三区av| 一本久久综合| 成人一区在线看| 日韩精品久久久久久| 精品动漫一区二区三区在线观看| 久久国产精品久久w女人spa| 99精品视频中文字幕| 午夜精品福利一区二区三区av| 久久久国产午夜精品| 亚洲视频碰碰| 国产麻豆精品theporn| 亚洲一区二区三区爽爽爽爽爽 | 噜噜噜91成人网| 91在线高清观看| 免费成人在线影院| 综合激情网...| 制服视频三区第一页精品| 日韩五码在线| av福利精品导航| 日韩国产在线观看一区| 国产精品免费视频网站| 欧美精品1区2区3区| 亚洲欧美久久久久一区二区三区| 你懂的视频一区二区| 国产一区二区三区在线看麻豆| 亚洲激情男女视频| 国产日韩欧美精品一区| 3atv一区二区三区| 久久综合电影| 伊人成人在线| 99久久99久久精品免费看蜜桃| 久久精品国产**网站演员| 亚洲精品久久久蜜桃| 久久久久综合网| 7777女厕盗摄久久久| 久久婷婷丁香| 国产欧美日韩综合一区在线播放| 欧美高清不卡| 成人午夜碰碰视频| 国产资源精品在线观看| 丝袜美腿成人在线| 一区二区三区四区不卡视频 | 日韩av一区二区三区四区| 中文字幕综合网| 国产视频在线观看一区二区三区| 3751色影院一区二区三区| 色婷婷精品大视频在线蜜桃视频| 一二三区精品| 亚洲视频综合| 欧美视频成人| 欧美激情国产日韩| av激情综合网| 99久久久国产精品免费蜜臀| 国产成人日日夜夜| 国产精品一线二线三线| 麻豆精品国产91久久久久久| 日韩和欧美一区二区| 亚洲成人av一区| 亚洲激情图片小说视频| 亚洲图片你懂的| 国产欧美日韩在线| 国产亚洲一二三区| 中文久久乱码一区二区| 国产精品久久久久久一区二区三区| 国产精品视频一二三| 亚洲视频 欧洲视频| 亚洲精品成人在线| 亚洲高清在线精品| 奇米影视一区二区三区| 黄一区二区三区| 国产白丝网站精品污在线入口| 国产91丝袜在线观看| 岛国精品在线播放| 91在线视频播放地址| 国产精品国产精品| 99精品国产一区二区青青牛奶| 国产日韩1区| 久久精品国产清高在天天线 | 欧美精品自拍偷拍| 91精品在线麻豆| 2020国产精品| 国产精品视频你懂的| 亚洲欧美日韩在线播放| 亚洲国产一区视频| 久久草av在线| 国产成人av影院| 午夜精品久久99蜜桃的功能介绍| 在线观看成人av电影|