"""
ORM思路归纳: 1、将每张表映射成不同的表类,一个表类映射一张表。表类的类属性
需要有表名、字段名
将每个字段类型映射为字段类型类,一个字段类型类映射一个类
字段类实例化需要传入有字段名、字段类型、是否是主键、默认值
等参数,其中除字段名外其他参数可设置默认值
2、每个表类都有相同的基础属性,如表名,主键字段,增删改查方法,
那么由此就可以抽离出Models基类,相同属性和方法同一抽到基类,
不涉及需要每个表区别属性的方法我们把它抽为基类类方法。
3、考虑到一条数据库数据需要产生一个对象,用pymysql查询得到得可以
是字典类型,那么我们可以将基类Models继承dict,用__setattr__
将字段转换为伪对象属性操作,用__getattr__对属性取值
由基类查询一条或者多条数据的类方法,将得到的记录本身传给表类
自身实例化得到对象,用__setattr__将字段作为对象属性,这样一
个对象就可以映射一条数据
4、为了更好的实现对数据库表的映射,我们需要创建元类来对定义的表类
的控制,如一个表只且只有一个主键,规范每个表类的属性名称,比如
表名、主键名,其他字段集合
5、另外要实现对数据库操作提交,这部分功能不适合做在基类表类中,做在
表类中会让表类臃肿且逻辑不清,我们将其专门定义一个数据库连接类,
表这一部分就负责实现功能,具体对数据库通信操作由数据库连接类去完成 """ # 实现代码 class Field(object):
"""
Field:映射数据库字段 基类
name:字段名
culomn_type:字段类型
primary_key:是否是主键
default:默认值
"""
def __init__(self,name,culomn_type,primary_key,default):
self.name = name
self.culomn_type = culomn_type
self.primary_key = primary_key
self.default = default class IntField(Field):
"""
继承Field基类,实现对int类型字段的映射
"""
def __init__(self,name,culomn_type = "int",primary_key = False,default = 0):
super().__init__(name,culomn_type,primary_key,default) class PrimaryField(Field):
"""
继承Field基类,实现对主键字段的映射
"""
def __init__(self,name,culomn_type,primary_key = True, default = None):
super().__init__(name,culomn_type,primary_key,default) class StringField(Field):
"""
继承Field基类,实现对char类型字段的映射
"""
def __init__(self,name,culomn_type = "varchar(64)", primary_key = False,default = ""):
super().__init__(name,culomn_type,primary_key,default) # 你还可以继续定义其他类型字段类,如日期等 class MyMeta(type):
"""
自定义元类,实现对每张表映射的表类的属性控制
如:1、限制一个表有且只能有一个主键,否则创建派生类失败
2、将表的字段属性全部放到一个字典里,然后把这个字典整体放入类的名称空间
"""
def __new__(cls, class_name, class_bases, class_space): # 控制类产生
if class_name == "Models": # 对 Models类不生效
# 所有表类由Models类派生
return type.__new__(cls,class_name,class_bases, class_space) table_name = class_space.get("table_name")
primary_key = None
mappings = {}
for k,v in class_space.items():# 筛选出主键
if isinstance(v,Field):
mappings[k] = v
if v.primary_key:
if primary_key:
raise TypeError("一个表只能有一个主键")
primary_key = v
for key in mappings.keys(): # 将原名称空间中的所有字段属性删除
class_space.pop(key) class_space["table_name"] = table_name
class_space["primary_key"] = primary_key # 将筛选出来的属性重新装回类名称空间
class_space["mappings"] = mappings # 将字段属性装入mapping再装回原名称空间 return type.__new__(cls,class_name,class_bases,class_space) # 调回type__new__ class Models(dict,metaclass = MyMeta):
def __init__(self,**kwargs):
super().__init__(**kwargs) def __getattr__(self, item):
return self.get(item) def __setattr__(self, key, value):
self[key] = value @classmethod
def select(cls,**kwargs): # 查询表单条或多条记录,并实例化记录为对象返回
mysql = Mysql.create_instance()
if not kwargs:
sql = "select * from %s"%cls.table_name
res = mysql.select(sql)
else:
k = list(kwargs.keys())[0]
v = kwargs.get(k)
sql = "select * from %s where %s = $"%(cls.table_name,k)
sql = sql.replace("$","%s")
res = mysql.select(sql,(v,))
if res:
return [cls(**r) for r in res] import pymysql
class Mysql(object) :
_instance = None
def __init__(self): # 建立数据库连接
self.conn = pymysql.connect(
host = "127.0.0.1",
port = 3306,
user = "root",
password = "",
database = "class",
charset = "utf8",
autocommit = True
)
self.cursor = self.conn.cursor(pymysql.cursors.DictCursor) # 设置查询返回数据格式为列表套字典 @classmethod
def create_instance(cls): # 创建单例
if not cls._instance:
cls._instance = cls()
return cls._instance def select(self,sql,arg = None): # 提交数据库操作
if not arg:
try:
self.cursor.execute(sql)
except BaseException as e:
print(e)
return
else:
try:
self.cursor.execute(sql,arg)
except BaseException as e:
print(e)
return
res = self.cursor.fetchall() # 拿到所有返回结果
return res if __name__ == '__main__':
class Course(Models): # course表类
table_name = "course"
cid = PrimaryField(name = "cid",culomn_type="int") # 表id字段 创建主键字段对象
cname = StringField(name = "cname") # 表cname字段,创建字符串类型对象 res = Course.select(cid = 3) # 查找cid = 3的记录并实例化对象返回
print(res[0].cname)
print(res[0].mappings)

python 其实不用框架你也可以实现ORM的更多相关文章

  1. python的Web框架,Django的ORM,模型基础,MySQL连接配置及增删改查

    Django中的ORM简介 ORM概念:对象关系映射(Object Relational Mapping,简称ORM): 用面向对象的方式描述数据库,去操作数据库,甚至可以达到不用编写SQL语句就能够 ...

  2. Python 并行分布式框架 Celery

    Celery 简介 除了redis,还可以使用另外一个神器---Celery.Celery是一个异步任务的调度工具. Celery 是 Distributed Task Queue,分布式任务队列,分 ...

  3. 谈谈Python中元类Metaclass(二):ORM实践

    什么是ORM? ORM的英文全称是“Object Relational Mapping”,即对象-关系映射,从字面上直接理解,就是把“关系”给“对象”化. 对应到数据库,我们知道关系数据库(例如Mys ...

  4. 【转】Python 并行分布式框架 Celery

    原文链接:https://blog.csdn.net/freeking101/article/details/74707619 Celery 官网:http://www.celeryproject.o ...

  5. Python之Web框架Django

    Python之Web框架: Django 一. Django Django是一个卓越的新一代Web框架 Django的处理流程 1. 下载地址  Python 下载地址:https://www.pyt ...

  6. Python 常用Web框架的比较

    转载来自:https://www.cnblogs.com/sunshine-1/p/7372934.html 从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OL ...

  7. python各种web框架对比

    0 引言        python在web开发方面有着广泛的应用.鉴于各种各样的框架,对于开发者来说如何选择将成为一个问题.为此,我特此对比较常见的几种框架从性能.使用感受以及应用情况进行一个粗略的 ...

  8. python+selenium+unnittest框架

    python+selenium+unnittest框架,以百度搜索为例,做了一个简单的框架,先看一下整个项目目录结构 我用的是pycharm工具,我觉得这个工具是天使,超好用也超好看! 这些要感谢原作 ...

  9. python三大web框架Django,Flask,Flask,Python几种主流框架,13个Python web框架比较,2018年Python web五大主流框架

    Python几种主流框架 从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OLAP,Web开发,高性能网络通信,测试,爬虫等. Django: Python We ...

随机推荐

  1. ORM高阶补充:only, defer,select_related

    Queryset官方文档:https://docs.djangoproject.com/en/1.11/ref/models/querysets/ 1.需求1:只取某n列 1.方法1:values 2 ...

  2. Laravel 事件侦听的几个方法 [Trait, Model boot(), Observer Class]

    1 Trait 1.1 可以在 Trait 中定义一个静态的 bootFooBar() 方法,注:FooBar 是你的 Trait 名称 namespace App\Traits; use App\A ...

  3. 一个参数既可以是const还可以是volatile

    可以的,例如只读的状态寄存器.它是volatile因为它可能被意想不到地改变.它是const因为程序不应该试图去修改它. 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器 ...

  4. 科大讯飞语音转文字,ffmpeg将wav转成pcm二进制音频文件

    百度和讯飞和其他厂都提供了语音识别的接口,这里使用讯飞的识别将本地手机录的音频文件转成文字 以下注意事项: 1.X_Param 参数开始的时候带了空格导致验证不过,原因是讯飞将字符串做了repelce ...

  5. Java线程之创建线程

    翻译自:https://www.journaldev.com/1016/java-thread-example 进程 进程是一个自包含的执行环境,它可以被看成一个程序或应用程序.然而一个应用程序本身包 ...

  6. 预处理、const、static与sizeof-为什么不把所有的函数都定义成内联函数

    1:内联是以代码膨胀(复制)为代价的,仅仅省去了函数调用的开销,从而提高函数的执行效率.如果执行函数体内代码的时间相比于函数调用的开销较大,那么效率的收获会很小.另一方面,每一处内联函数的调用都要复制 ...

  7. Qt高级——QTestLib单元测试框架

    一.QTestLib简介 1.QTestLib简介 QTestLib是Qt提供的一种针对基于Qt编写的程序或库的单元测试框架.QTestLib提供了单元测试框架的基本功能,并提供了针对GUI测试的扩展 ...

  8. Qt 插件学习(一)

    插件是什么 注意:这儿暂时不考虑静态插件(潜意识中总觉得它根本就不算插件). 插件是一个动态库(共享库).动态库是一个独立的文件中的独立模块,可被多个程序访问. 先看动态库的两种用法 1. 程序链接时 ...

  9. centos6安装sshpass

    跳转机需要装这个 #!/bin/bash yum -y install gcc-c++ openssh-clients curl -o sshpass.tar.gz http://sourceforg ...

  10. koa 项目实战(七)登录接口

    1.登录接口 /** * @route POST api/users/login * @desc 登录接口地址 * @access 接口是公开的 */ router.post('/login', as ...