当前位置: 首页 > news >正文

用Metaclass实现一个精简的ORM框架

存档:

 1 # -*- coding: utf-8 -*-
 2 class Field(object):
 3 
 4     def __init__(self, name, column_type):
 5         self.name = name
 6         self.column_type = column_type
 7 
 8     def __str__(self):
 9         return '<%s:%s>' % (self.__class__.__name__, self.name)
10 class StringField(Field):
11 
12     def __init__(self, name):
13         super(StringField, self).__init__(name, 'varchar(100)')
14 
15 class IntegerField(Field):
16 
17     def __init__(self, name):
18         super(IntegerField, self).__init__(name, 'bigint')
19 class ModelMetaclass(type):
20 
21     def __new__(cls, name, bases, attrs):
22         if name=='Model':
23             return type.__new__(cls, name, bases, attrs)
24         print('Found model: %s' % name)
25         mappings = dict()
26         for k, v in attrs.items():
27             if isinstance(v, Field):
28                 print('Found mapping: %s ==> %s' % (k, v))
29                 mappings[k] = v
30         for k in mappings.keys():
31             attrs.pop(k)
32         attrs['__mappings__'] = mappings # 保存属性和列的映射关系
33         attrs['__table__'] = name # 假设表名和类名一致
34         return type.__new__(cls, name, bases, attrs)
35 class Model(dict, metaclass=ModelMetaclass):
36 
37     def __init__(self, **kw):
38         super(Model, self).__init__(**kw)
39 
40     def __getattr__(self, key):
41         try:
42             return self[key]
43         except KeyError:
44             raise AttributeError(r"'Model' object has no attribute '%s'" % key)
45 
46     def __setattr__(self, key, value):
47         self[key] = value
48 
49     def save(self):
50         fields = []
51         params = []
52         args = []
53         for k, v in self.__mappings__.items():
54             fields.append(v.name)
55             params.append('?')
56             args.append(getattr(self, k, None))
57         sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
58         print('SQL: %s' % sql)
59         print('ARGS: %s' % str(args))
60 class User(Model):
61     # 定义类的属性到列的映射:
62     id = IntegerField('id')
63     name = StringField('username')
64     email = StringField('email')
65     password = StringField('password')
66 # 创建一个实例:
67 u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
68 # 保存到数据库:
69 u.save()

结果如下:

Found model: User
Found mapping: id ==> <IntegerField:id>
Found mapping: name ==> <StringField:username>
Found mapping: email ==> <StringField:email>
Found mapping: password ==> <StringField:password>
SQL: insert into User (id,username,email,password) values (?,?,?,?)
ARGS: [12345, 'Michael', 'test@orm.org', 'my-pwd']
[Finished in 0.2s]

相关文章:

  • 看不到短期回报,首席财务官们表示对AI并不感冒
  • 杂感一篇
  • 影响存储快照使用率的六大因素
  • 寒假作业02
  • 绝对路径和相对路径
  • rabbitmq延迟消息示例
  • JS易混淆的方法整理
  • 转型成亚洲三大通信展主题 中国企业参与积极
  • 诡异!React stopPropagation失灵
  • Unix环境高级编程(四)数据系统文件和信息
  • 算法初级之二
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • 人民日报发声,区块链成“兵家必争之地”,或成“国家战略”
  • iOS下JS与OC互相调用(八)--Cordova详解+实战
  • itextsharp display:none无效的bug
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • C++入门教程(10):for 语句
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • JDK 6和JDK 7中的substring()方法
  • js中的正则表达式入门
  • Laravel Mix运行时关于es2015报错解决方案
  • PHP的Ev教程三(Periodic watcher)
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Tornado学习笔记(1)
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 实现菜单下拉伸展折叠效果demo
  • 我有几个粽子,和一个故事
  • 消息队列系列二(IOT中消息队列的应用)
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • #if和#ifdef区别
  • #考研#计算机文化知识1(局域网及网络互联)
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (Python第六天)文件处理
  • (笔试题)分解质因式
  • (动态规划)5. 最长回文子串 java解决
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (五)MySQL的备份及恢复
  • (转)大型网站的系统架构
  • (转载)Google Chrome调试JS
  • .Net CF下精确的计时器
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • [BZOJ 4598][Sdoi2016]模式字符串
  • [C++]高精度 bign (重载运算符版本)
  • [ffmpeg] 定制滤波器
  • [HOW TO]怎么在iPhone程序中实现可多选可搜索按字母排序的联系人选择器
  • [I2C]I2C通信协议详解(一) --- 什么是I2C
  • [idea]关于idea开发乱码的配置
  • [LeetCode]剑指 Offer 42. 连续子数组的最大和
  • [luoguP1666] 前缀单词(DP)
  • [NOIP 2003] 栈(三种方法:DP、数论、搜索)