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 ...
随机推荐
- springboot2.0入门(一)----springboot 简介
一.springboot解决了什么? 避免了繁杂的xml配置,框架自动帮我们完成了相关的配置,当我们需要进行相关插件集成的时候,只需要将相关的starter通过相关的maven依赖引进,并可以进行相关 ...
- 【转】css样式的书写顺序及原理——很重要!
记得刚开始学习前端的时候,每次写css样式都是用到什么就在样式表后添加什么,完全没有考虑到样式属性的书写顺序对网页加载代码的影响.后来逐渐才知道正确的样式顺序不仅易于查看,并且也属于css样式优化的一 ...
- laravel各种请求类
curl请求类 composer require php-curl-class/php-curl-class
- shell 脚本拉取svn代码,vim中文乱码解决办法
VIM安装成功后可以使用,但对中文是乱码,解决方法是在vim的配置文档中添加相关设置即可: 找到etc/vimrc 编辑~/.vimrc文件,加上如下几行: set fileencodings=utf ...
- CPU内部结构图
原文地址:http://blog.csdn.net/jiuyueguang/article/details/9350793
- [JSOI 2016] 最佳团体(树形背包+01分数规划)
4753: [Jsoi2016]最佳团体 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2003 Solved: 790[Submit][Statu ...
- 《30天自制操作系统》学习笔记--番外篇之Mac环境下的工具介绍
这几天又有点不务正业了,书也没看,一直在搞这个破环境,尝试各种做法,网上各种垃圾信息,浪费了很多时间,说的基本都是废话,不过还是找到了一些,赶紧写下来,不然这个过几天又忘了 首先是环境,我用的是Max ...
- 日期与时间(C/C++)
C++继承了C语言用于日期和时间操作的结构和函数,使用之前程序要引用<ctime>头文件 有四个与时间相关的类型:clock_t.time_t.size_t.和tm.类型clock_t.s ...
- C语言实现简单的哈希表
这是一个简单的哈希表的实现,用c语言做的. 哈希表原理 这里不讲高深理论,只说直观感受.哈希表的目的就是为了根据数据的部分内容(关键字),直接计算出存放完整数据的内存地址. 试想一下,如果从链表中根据 ...
- Django基础之命名URL和URL反向解析
在使用Django项目时,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等). 人们强烈希望不要硬编码这些URL(费力 ...