Python - 动手写个ORM

任务:

  1. 模拟简单的ORM - Object Relational Mapping
  2. 为model添加create方法

代码很简单,直接上

字段类型类


class Field(object):
"""docstring for Field""" def __init__(self, field_type, default, max_length, * arg):
super().__init__()
self.default = default
self.max_length = max_length
self.field_type = field_type class CharField(Field):
"""docstring for CharField""" def __init__(self, max_length=100, *arg):
super().__init__('char', '', max_length) class DateField(Field):
"""docstring for DateField""" def __init__(self, default='now', *arg):
if(default == 'now'):
from datetime import datetime
self.default = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
else:
self.default = default
super().__init__('datetime', self.default, None) class IntField(Field):
"""docstring for IntField""" def __init__(self, default=0, *arg):
super().__init__('int', 0, 8)

很关键的MetaClass


class ModelMetaClass(type):
"""docstring for ModelMetaClass""" def __new__(cls, name, bases, attrs):
print('2. ModelMetaClass __new__')
mapping = {}
# mapping = dict()
for k, v in attrs.items():
if(isinstance(v, Field)):
mapping[k] = v
for k, v in mapping.items():
del attrs[k] # 挂到实例上
# attrs['mapping'] = mapping
cls_obj = type.__new__(cls, name, bases, attrs) # 这里为了测试效果简单的将需要的信息添加到类的动态属性上
cls_obj.mapping = mapping
cls_obj.table = name return cls_obj # 如果子类中指定metaclass那么必须从父类的meta继承以维持正确的调用顺序
class NewsMetaClass(ModelMetaClass):
"""docstring for NewsMetaClass"""
print('1. NewsMetaClass __new__') def __new__(cls, name, bases, attrs):
# do anything you want # attrs['create'] = NewsMetaClass.create clsobj = super().__new__(cls, name, bases, attrs)
return clsobj

Model类, 注意metaclass的设定

class Model(object, metaclass=ModelMetaClass):
"""docstring for Model""" def __init__(self, *arg):
super(Model, self).__init__()
self.arg = arg @classmethod
def create(cls, **kwargs):
fields = []
params = []
args = [] for k, v in cls.mapping.items():
fields.append(k)
params.append('?')
args.append(kwargs[k]) sql = 'insert into %s (%s) values(%s)' % (cls.table, ','.join(fields), ','.join(params))
param = ','.join(args)
print('SQL: %s' % (sql))
print('args: %s' % param)
# exec the sql class News(Model, metaclass=NewsMetaClass):
"""docstring for News"""
title = CharField(max_length=100)
content = CharField(max_length=500)
publish_date = DateField(default="now")
read_count = IntField(default=0)

测试效果

from datetime import datetime
News.create(title='test', content='asdf', read_count='0', publish_date=datetime.now().strftime('%Y-%m-%d %H:%M:%S')) # SQL: insert into News (publish_date,content,title,read_count) values(?,?,?,?)
# args: 2016-05-16 22:39:54,asdf,test,0

参考:使用元类

Python - 动手写个ORM的更多相关文章

  1. 自己动手写ORM的感受

    之前看到奋斗前辈和时不我待前辈的自己动手写ORM系列博客,感觉讲解的通俗易懂,清晰透彻.作为一个菜鸟,闲来也想着自己写一个ORM,一来加深自己对 ORM的理解,以求对EF,NHibernate等ROM ...

  2. (新)自己动手写ORM框架(1)-增删查改的使用

    之前写过一个系列文章自己动手写ORM框架,经过在多个项目的中的使用,对这套代码进行了许多改进,下面是使用方法: 新增学员信息代码预览: DBHelper db = DBHelper.getInstan ...

  3. SQLAlchemy(1) -- Python的SQLAlchemy和ORM

    Python的SQLAlchemy和ORM(object-relational mapping:对象关系映射) web编程中有一项常规任务就是创建一个有效的后台数据库.以前,程序员是通过写sql语句, ...

  4. 自己动手写Spring框架--IOC、MVC

    对于一名Java开发人员,我相信没有人不知道 Spring 框架,而且也能够轻松就说出 Spring 的特性-- IOC.MVC.AOP.ORM(batis). 下面我想简单介绍一下我写的轻量级的 S ...

  5. 手写开源ORM框架介绍

    手写开源ORM框架介绍 简介 前段时间利用空闲时间,参照mybatis的基本思路手写了一个ORM框架.一直没有时间去补充相应的文档,现在正好抽时间去整理下.通过思路历程和代码注释,一方面重温下知识,另 ...

  6. 动手写一个简单的Web框架(HelloWorld的实现)

    动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...

  7. 60行自己动手写LockSupport是什么体验?

    60行自己动手写LockSupport是什么体验? 前言 在JDK当中给我们提供的各种并发工具当中,比如ReentrantLock等等工具的内部实现,经常会使用到一个工具,这个工具就是LockSupp ...

  8. 自己动手写ls命令——Java版

    自己动手写ls命令--Java版 介绍 在前面的文章Linux命令系列之ls--原来最简单的ls这么复杂当中,我们仔细的介绍了关于ls命令的使用和输出结果,在本篇文章当中我们用Java代码自己实现ls ...

  9. 自己动手写线程池——向JDK线程池进发

    自己动手写线程池--向JDK线程池进发 前言 在前面的文章自己动手写乞丐版线程池中,我们写了一个非常简单的线程池实现,这个只是一个非常简单的实现,在本篇文章当中我们将要实现一个和JDK内部实现的线程池 ...

随机推荐

  1. c#对数据库访问完应关闭连接

    1.对数据库的连接SqlConnection con = new SqlConnection(constr);使用完成后,应该至少应该close或dispose关闭.否则会导致数据库例如(SQl200 ...

  2. 算法入门笔记------------Day1

    1.C语言使用%d显示float值,不会把float值转换为近似的int值,而是显示垃圾值,使用%f显示int值,也不会把该int值转换为浮点值 2.三位数反转:输入一个三位数,分离它的百位,十位和个 ...

  3. Python 10 —— 杂

    Python 10 —— 杂 科学计算 NumPy:数组,数组函数,傅里叶变换 SciPy:依赖于NumPy,提供更多工具,比如绘图 绘图 Matplitlib:依赖于NumPy和Tkinter

  4. Postman-进阶

    Postman-简单使用 Postman-进阶使用 Postman-CI集成Jenkins 管理请求 保存请求-添加“打开百度首页请求” 设置请求方式为Get,地址为www.baidu.com.点击右 ...

  5. padding(内边距)、margin(外边距)、border(边框)

    元素的 padding 控制元素内容 content和元素边框 border 之间的距离. 元素的外边距 margin 控制元素边框 border 和元素实际所占空间的距离,如果你将一个元素的 mar ...

  6. mentohust 你让我如何说你是好呢?

    最近换了ubuntu系统结果热了不少的麻烦,  借此机会唠叨一下, 首先是你这个ubuntu16.4 你这个bug 太让人郁闷了吧,或许主要是应该怪我菜,装个看家的软件eclipse.还热除了一堆的麻 ...

  7. springmvc No mapping found for HTTP request with URI in Dispatc

    springmvc No mapping found for HTTP request with URI in Dispatc 博客分类: Java Web springmvcspring MVCNo ...

  8. minigui编译

    1, libminigui修改单 file: src/kernel/desktop.c func: def_mouse_handler keywords: MSG_DT_RBUTTONUP break ...

  9. Django如何搭建服务器

    建立django站点: 新建Django项目,我这里是使用命令创建项目的. django-admin startproject HelloDjango  创建HelloDjango项目 然后进入到He ...

  10. [leetcode 27]Implement strStr()

    1 题目: Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if ...