# coding: utf-8

#
# Python MySQL ORM QuickORM hacking
# 说明:
# 以前仅仅是知道有ORM的存在,但是对ORM这个东西内部工作原理不是很清楚,
# 这次正好需要用到,于是解读一个相对来说很简单的Python2 ORM的例子。
#
# 参考源码:
# A simple ORM provides elegant API for Python-MySQL operation
# https://github.com/2shou/QuickORM
#
# 2016-10-15 深圳 南山平山村 曾剑锋 import MySQLdb #
# 作为和数据库中字段对应的域,同样也作为类属性存在
#
class Field(object):
pass class Expr(object):
# 合成where查询部分
def __init__(self, model, kwargs):
self.model = model
# How to deal with a non-dict parameter?
# 提取键值对的value部分
self.params = kwargs.values()
# 提取键值对的key部分,并合成替代字符串
equations = [key + ' = %s' for key in kwargs.keys()]
self.where_expr = 'where ' + ' and '.join(equations) if len(equations) > 0 else '' def update(self, **kwargs):
_keys = []
_params = []
# 筛选数据
for key, val in kwargs.iteritems():
if val is None or key not in self.model.fields:
continue
_keys.append(key)
_params.append(val) # 和__init__中的键值对的values数据联合
_params.extend(self.params)
# 合成查询语句
sql = 'update %s set %s %s;' % (
self.model.db_table, ', '.join([key + ' = %s' for key in _keys]), self.where_expr)
return Database.execute(sql, _params) def limit(self, rows, offset=None):
# 合成limit数据,这里就是合成想从那一行开始取数据,取多少数据
self.where_expr += ' limit %s%s' % (
'%s, ' % offset if offset is not None else '', rows)
return self def select(self):
# 合成查询语句,需要查询的字段,表明,条件
sql = 'select %s from %s %s;' % (', '.join(self.model.fields.keys()), self.model.db_table, self.where_expr)
# 取出所有的数据,这里使用了yield,使得select可以被for in语法再次迭代从而获取到值
for row in Database.execute(sql, self.params).fetchall():
# 获取传入的模板类型,这样就不用知道是什么类运行了select
inst = self.model()
# 获取一条信息中的值
for idx, f in enumerate(row):
setattr(inst, self.model.fields.keys()[idx], f)
yield inst # 返回查询的数据统计总数
def count(self):
sql = 'select count(*) from %s %s;' % (self.model.db_table, self.where_expr)
(row_cnt, ) = Database.execute(sql, self.params).fetchone()
return row_cnt class MetaModel(type):
db_table = None
fields = {} def __init__(cls, name, bases, attrs):
super(MetaModel, cls).__init__(name, bases, attrs)
fields = {}
# 从类所有的属性中提取出类属性,和数据库中的字段对应,这里更多的给Expr类使用。
for key, val in cls.__dict__.iteritems():
if isinstance(val, Field):
fields[key] = val
cls.fields = fields
cls.attrs = attrs class Model(object):
# 采用MetaModel来构建Model类
__metaclass__ = MetaModel # 动态生成对应的sql语句,并执行对应的语句,要注意这里是self.__dict__获取的实例属性。
def save(self):
insert = 'insert ignore into %s(%s) values (%s);' % (
self.db_table, ', '.join(self.__dict__.keys()), ', '.join(['%s'] * len(self.__dict__)))
return Database.execute(insert, self.__dict__.values()) # 使用where来查询
@classmethod
def where(cls, **kwargs):
return Expr(cls, kwargs) class Database(object):
autocommit = True
conn = None
db_config = {} # 通过db_config字典数据设置连接数据库的值
@classmethod
def connect(cls, **db_config):
cls.conn = MySQLdb.connect(host=db_config.get('host', 'localhost'), port=int(db_config.get('port', 3306)),
user=db_config.get('user', 'root'), passwd=db_config.get('password', ''),
db=db_config.get('database', 'test'), charset=db_config.get('charset', 'utf8'))
cls.conn.autocommit(cls.autocommit)
cls.db_config.update(db_config) # 这里是连接数据库,里面有一些策略,譬如:
# 1. 如果没有连接数据库,那么就连接数据库;
# 2. 如果连接了数据库,那么测试是否可ping通再返回连接;
# 3. 如果ping不通,那么重新连接,再返回。
@classmethod
def get_conn(cls):
if not cls.conn or not cls.conn.open:
cls.connect(**cls.db_config)
try:
cls.conn.ping()
except MySQLdb.OperationalError:
cls.connect(**cls.db_config)
return cls.conn # 这里是直接执行sql语句,返回的是执行后的cursor
@classmethod
def execute(cls, *args):
cursor = cls.get_conn().cursor()
cursor.execute(*args)
return cursor # 对象被垃圾回收机回收的时候调用
def __del__(self):
if self.conn and self.conn.open:
self.conn.close() # 执行原始sql语句
def execute_raw_sql(sql, params=None):
return Database.execute(sql, params) if params else Database.execute(sql)

Python MySQL ORM QuickORM hacking的更多相关文章

  1. python mysql orm

    Python中操作mysql的pymysql模块详解:https://www.cnblogs.com/wt11/p/6141225.html Python 12 - Mysql & ORM:h ...

  2. python 之路,Day11(上) - python mysql and ORM

    python 之路,Day11 - python mysql and ORM   本节内容 数据库介绍 mysql 数据库安装使用 mysql管理 mysql 数据类型 常用mysql命令 创建数据库 ...

  3. 冰冻三尺非一日之寒-mysql(orm/sqlalchemy)

    第十二章  mysql ORM介绍    2.sqlalchemy基本使用 ORM介绍: orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似pyt ...

  4. 10分钟教你Python+MySQL数据库操作

    欲直接下载代码文件,关注我们的公众号哦!查看历史消息即可! 本文介绍如何利用python来对MySQL数据库进行操作,本文将主要从以下几个方面展开介绍: 1.数据库介绍 2.MySQL数据库安装和设置 ...

  5. Python—>Mysql—>Dbvisualizer

    MySQLdb: https://pypi.python.org/pypi/MySQL-python/1.2.4 import MySQLdb 1.Download Connector/Python: ...

  6. Python Mysql 篇

    Python 操作 Mysql 模块的安装 linux: yum install MySQL-python window: http://files.cnblogs.com/files/wupeiqi ...

  7. 树莓派安装ubuntu-server,配置镜像,安装python/mysql/samba记录

    目标: 1/在raspberrypi 3B上安装ubuntu-server 2/配置好python/mysql/samba等服务,实现爬虫稳定运行我的硬件准备: 1/raspberrypi 3B 2/ ...

  8. Python/ MySQL练习题(一)

    Python/ MySQL练习题(一) 查询“生物”课程比“物理”课程成绩高的所有学生的学号 SELECT * FROM ( SELECT * FROM course LEFT JOIN score ...

  9. python/MySQL练习题(二)

    python/MySQL练习题(二) 查询各科成绩前三名的记录:(不考虑成绩并列情况) select score.sid,score.course_id,score.num,T.first_num,T ...

随机推荐

  1. 一个简单的excel文件上传到数据库方法

    因为以前项目中有用到过Excel导入,所以整理了一下,这是一个导入Excel数据到数据库的方法 注意:需要导入poi jar包 代码清单 /** * Excel 导入 * @param mapping ...

  2. jquery删除原事件

    $(document).ready(function(){ var fn = $("#exportCsv").attr( "onclick" ); // 获取原 ...

  3. bzoj 2730: [HNOI2012]矿场搭建

    #include<cstdio> #include<cstring> #include<iostream> #define M 508 using namespac ...

  4. HDU 3265 扫描线(矩形面积并变形)

    Posters Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  5. hdu 4607 Park Visit

    http://acm.hdu.edu.cn/showproblem.php?pid=4607 先求树的直径 方法:两遍bfs ,任选一点 a  求到a点最远的一点b ,然后 求到b点最远点 c 这样 ...

  6. winform插入sql的事务处理

    实现目的:点击按钮,原子性执行两条sql语句,同时成功或同时失败 数据库有这三个字段(忽略已有的一条记录): 一.用事务的sql语句 按钮事件完整代码: //事务处理插入sql语句 using (SQ ...

  7. 建议入门-用ArcMap进行空间查询与空间连接

    1.打开arcmap并导入数据(如本图导入美国地图(usa.mxd)): 2.空间查询操作,在地图上的某片区域点击右键,得到下图,点击identify,此时我在阿拉斯加上面点击的 地图会闪现一下被查询 ...

  8. 统计一段文字中出现频率最高的10个单词(c语言)

    注:这次使用C语言做的这个程序.个别不懂的地方和算法部分是请教的其他同学,交流并吸收,所以收获颇多! 在程序中每一个地方我都做了注释,方便同学之间交流.也让老师容易看.程序也有很多不足的地方,但限于本 ...

  9. CDH上执行WordCount的意外和收获

    前面将Cloudera Manager安装到集群上的一台主机后,并通过Cloudera manager安装了hadoop-2.6.0-CDH5.4.4.今日来测试安装的集群是否很够很好的执行mapre ...

  10. 内部类中class声明地方不同,效果不一样

    1.一个声明在类中,一个声明在类的方法中.在类中的方法中声明内部类,其方法中的内部类调用 内部类外中的变量,变量必须final class Outter{ int x1 = 0; public voi ...