"""
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. 将网页上指定的表单的数据导入到excel中

    很多时候,我们想要将网页上显示的信息,导入到Excel中,但是很多时候无法下手.可是,这个时候,下面这个例子会帮你大忙了. 将html表单指定内容导出到EXCEL中. <!DOCTYPE HTM ...

  2. C语言位运算题解

    #include <stdio.h> #include <stdlib.h> #include <string.h> //#define NONBLANK 1 ma ...

  3. nextAll([expr]) 查找当前元素之后所有的同辈元素。

    nextAll([expr]) 概述 查找当前元素之后所有的同辈元素. 可以用表达式过滤 参数 exprStringV1.2 用来过滤的表达式 示例 描述: 给第一个div之后的所有元素加个类直线电机 ...

  4. PHP mysqli_more_results() 函数

    定义和用法 mysqli_more_results() 函数检查一个多查询是否有更多的结果. 语法 mysqli_more_results(connection); 参数 描述 connection ...

  5. 封装Vue组件的一些技巧

    封装Vue组件的一些技巧 本文同步在个人博客shymean.com上,欢迎关注 写Vue有很长一段时间了,除了常规的业务开发之外,也应该思考和反思一下封装组件的正确方式.以弹窗组件为例,一种实现是在需 ...

  6. BZOJ 2834: 回家的路 Dijkstra

    按照横,竖为方向跑一个最短路即可,算是水题~ #include <bits/stdc++.h> #define N 200005 #define E 2000000 #define set ...

  7. TTTTTTTTTTTT Gym 100818B Tree of Almost Clean Money 树连剖分+BIT 模板题

    Problem B Tree of Almost Clean Money Input File: B.in Output File: standard output Time Limit: 4 sec ...

  8. Codeforces 959D. Mahmoud and Ehab and another array construction task(构造, 简单数论)

    Codeforces 959D. Mahmoud and Ehab and another array construction task 题意 构造一个任意两个数都互质的序列,使其字典序大等于a序列 ...

  9. 【分类模型评判指标 一】混淆矩阵(Confusion Matrix)

    转自:https://blog.csdn.net/Orange_Spotty_Cat/article/details/80520839 略有改动,仅供个人学习使用 简介 混淆矩阵是ROC曲线绘制的基础 ...

  10. 【Android】【踩坑日记】RecyclerView获取子View的正确姿势

    开发过程中发现RecyclerView.getChildAt(position)为空的情况,但是明明这个position却没有越界. 解决办法:用recycler.getLayoutManager() ...