python 其实不用框架你也可以实现ORM
"""
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的更多相关文章
- python的Web框架,Django的ORM,模型基础,MySQL连接配置及增删改查
Django中的ORM简介 ORM概念:对象关系映射(Object Relational Mapping,简称ORM): 用面向对象的方式描述数据库,去操作数据库,甚至可以达到不用编写SQL语句就能够 ...
- Python 并行分布式框架 Celery
Celery 简介 除了redis,还可以使用另外一个神器---Celery.Celery是一个异步任务的调度工具. Celery 是 Distributed Task Queue,分布式任务队列,分 ...
- 谈谈Python中元类Metaclass(二):ORM实践
什么是ORM? ORM的英文全称是“Object Relational Mapping”,即对象-关系映射,从字面上直接理解,就是把“关系”给“对象”化. 对应到数据库,我们知道关系数据库(例如Mys ...
- 【转】Python 并行分布式框架 Celery
原文链接:https://blog.csdn.net/freeking101/article/details/74707619 Celery 官网:http://www.celeryproject.o ...
- Python之Web框架Django
Python之Web框架: Django 一. Django Django是一个卓越的新一代Web框架 Django的处理流程 1. 下载地址 Python 下载地址:https://www.pyt ...
- Python 常用Web框架的比较
转载来自:https://www.cnblogs.com/sunshine-1/p/7372934.html 从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OL ...
- python各种web框架对比
0 引言 python在web开发方面有着广泛的应用.鉴于各种各样的框架,对于开发者来说如何选择将成为一个问题.为此,我特此对比较常见的几种框架从性能.使用感受以及应用情况进行一个粗略的 ...
- python+selenium+unnittest框架
python+selenium+unnittest框架,以百度搜索为例,做了一个简单的框架,先看一下整个项目目录结构 我用的是pycharm工具,我觉得这个工具是天使,超好用也超好看! 这些要感谢原作 ...
- python三大web框架Django,Flask,Flask,Python几种主流框架,13个Python web框架比较,2018年Python web五大主流框架
Python几种主流框架 从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OLAP,Web开发,高性能网络通信,测试,爬虫等. Django: Python We ...
随机推荐
- Codeforces Round #588 (Div. 2) E. Kamil and Making a Stream(DFS)
链接: https://codeforces.com/contest/1230/problem/E 题意: Kamil likes streaming the competitive programm ...
- PHP mysqli_info() 函数
定义和用法 mysqli_info() 函数返回有关最近执行查询的信息. 该函数作用于下列查询类型: INSERT INTO...SELECT... INSERT INTO...VALUES (... ...
- BZOJ 2815: [ZJOI2012]灾难 拓扑排序+倍增LCA
这种问题的转化方式挺巧妙的. Code: #include <bits/stdc++.h> #define N 100000 #define M 1000000 #define setIO ...
- Zabbix 数据库迁移
背景:ZABBIX的环境是LNMP,MySQL的架构是M-M主备模式,单台服务器SSD硬盘800G.监控主机日渐增多,空间不足,迁移到同样架构下的SAS盘2T空间. 架构:A 192.168.0.10 ...
- element-ui做表单验证 v-for遍历表单 自动生成校验规则 pc移动双适配
整体思路: 1:利用element-ui的栅格实现小分辨率和大分辨率的适配 2:模拟一组数据,从中筛选出 绑定各个表单值的对象 以及生成验证规则对象 3:在script标签内 .data()外,自 ...
- Python常用模块之hashlib模块
1.hashilib模块的功能 python的hashlib提供了常见的摘要算法,如MD5, SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换成一 ...
- Ubuntu切换登录用户和root用户
https://blog.csdn.net/master_ning/article/details/80733818
- flask 第九篇 蓝图 Blueprint
蓝图,听起来就是一个很宏伟的东西 在Flask中的蓝图 blueprint 也是非常宏伟的 它的作用就是将 功能 与 主服务 分开怎么理解呢? 比如说,你有一个客户管理系统,最开始的时候,只有一个查看 ...
- 15.反转链表 Java
题目描述 输入一个链表,反转链表后,输出新链表的表头. 思路 本题的关键就是在于对next域的赋值,同时对下一个节点进行保存,然后对把下一个节点赋给新的节点,这样依次循环完所有的节点.每次使新插入的节 ...
- BUUCTF平台-web-边刷边记录-1
1.WarmUp 思路很清晰,文件包含,漏洞点在代码会二次解码,只需注入一个?就可以使用../../进行路径穿越,然后去包含flag,flag路径在hint.php里面有 2.easy_tornado ...