Python 3 对象关系映射(ORM)
ORM
- 对象关系映射 Object Relational Mapping
- 表 ---> 类
- 字段 ---> 属性
- 记录 ---> 对象
# mysql_client.py
import pymysql
class MySQLClient:
def __init__(self):
# 建立连接
self.client = pymysql.connect(
host='localhost',
port=3306,
user='root',
password='123',
database='orm_demo',
charset='utf8',
autocommit=True
)
# 获取游标
self.cursor = self.client.cursor(
pymysql.cursors.DictCursor
)
# 提交查询sql语句并返回结果
def my_select(self, sql, value=None):
print('sql:', sql, '\nvalue:', value)
self.cursor.execute(sql, value)
res = self.cursor.fetchall()
return res
# 提交增加, 修改的sql语句
def my_execute(self, sql, values):
try:
print('<sql>:', sql, '\n<values>:', values)
self.cursor.execute(sql, values)
except Exception as e:
print(e)
# 关闭连接
def close(self):
self.cursor.close()
self.client.close()
# ORM.py
from mysql_client import MySQLClient
# 定义字段类
class Field:
def __init__(self, name, column_type, primary_key, default):
self.name = name
self.column_type = column_type
self.primary_key = primary_key
self.default = default
# 定义整数字段类
class IntegerField(Field):
def __init__(self, name, column_type='int', primary_key=False, default=0):
super().__init__(name, column_type, primary_key, default)
# 定义字符字段类
class StringField(Field):
def __init__(self, name, column_type='varchar(64)', primary_key=False, default=''):
super().__init__(name, column_type, primary_key, default)
# 定义元类
class OrmMetaClass(type):
def __new__(cls, class_name, class_bases, class_dict):
if class_name == 'Models':
return super().__new__(cls, class_name, class_bases, class_dict)
# 没有表名则默认等于类名
table_name = class_dict.get('table_name', class_name)
primary_key = None
# 定义一个空字典, 用来存放字段对象
mappings = {}
for key, value in class_dict.items():
# 筛选字段对象
if isinstance(value, Field):
mappings[key] = value
if value.primary_key:
if primary_key:
raise TypeError('只能有一个主键!')
primary_key = value.name
if not primary_key:
raise TypeError('必须有一个主键!')
# 删除class_dict中和mappings重复的字段属性
for key in mappings.keys():
class_dict.pop(key)
# 将表名添加到class_dict中
class_dict['table_name'] = table_name
# 将主键添加到class_dict中
class_dict['primary_key'] = primary_key
# 将mappings添加到class_dict中
class_dict['mappings'] = mappings
return super().__new__(cls, class_name, class_bases, class_dict)
# 定义Models类
class Models(dict, metaclass=OrmMetaClass):
def __getattr__(self, item):
return self.get(item)
def __setattr__(self, key, value):
self[key] = value
# 查询
@classmethod
def orm_select(cls, **kwargs): # kwargs --> {'id': 1}
mysql = MySQLClient()
# select * from User
if not kwargs:
sql = 'select * from %s' % cls.table_name
res = mysql.my_select(sql)
else:
key = list(kwargs.keys())[0]
value = kwargs.get(key)
sql = 'select * from %s where %s=?' % (cls.table_name, key)
sql = sql.replace('?', '%s')
res = mysql.my_select(sql, value)
mysql.close()
# 返回的是[{}]一个普通的字典(在列表内), 我们把这个字典传入Models类, 让其可以 "对象.属性"
return [cls(**d) for d in res] # d是一个字典
# 增加
def orm_insert(self):
mysql = MySQLClient()
# 存字段名
keys = []
# 存字段值
values = []
# 存 "?"
args = []
for k, v in self.mappings.items():
# 过滤主键, 因为主键是自增的
if not v.primary_key:
# 字段名
keys.append(v.name)
# 字段值, 没有值则使用默认值
values.append(
getattr(self, v.name, v.default)
)
# 有几个字段就存放几个"?"
args.append('?')
sql = 'insert into %s (%s) values (%s)' % (
self.table_name,
','.join(keys),
','.join(args)
)
sql = sql.replace('?', '%s')
print(sql)
print(values)
mysql.my_execute(sql, values)
mysql.close()
# 修改
def orm_update(self):
mysql = MySQLClient()
# 存字段名
keys = []
# 存字段值
values = []
# 主键值
primary_key = None
for k, v in self.mappings.items():
if v.primary_key:
# 获取主键值
primary_key = v.name + '= %s' % getattr(self, v.name)
else:
keys.append(v.name + '=?')
values.append(
getattr(self, v.name)
)
sql = 'update %s set %s where %s' % (
self.table_name,
','.join(keys),
primary_key
)
# sql: update table set k1=%s, k2=%s where id=pk
sql = sql.replace('?', '%s')
mysql.my_execute(sql, values)
mysql.close()
# 定义用户类
class User(Models):
user_id = IntegerField('user_id', primary_key=True)
user_name = StringField('user_name')
password = StringField('password')
user_obj = User.orm_select(user_id=1)[0] # 查询
print(user_obj) # {'user_id': 1, 'user_name': 'blake', 'password': '123'}
user_obj.user_name = 'bigb' # 修改user_name
user_obj.orm_update() # 将修改提交到数据库
Python 3 对象关系映射(ORM)的更多相关文章
- Android数据库框架——ORMLite轻量级的对象关系映射(ORM)Java包
Android数据库框架--ORMLite轻量级的对象关系映射(ORM)Java包 事实上,我想写数据库的念头已经很久了,在之前写了一个答题系统的小项目那只是初步的带了一下数据库,数据库是比较强大的, ...
- 对象关系映射ORM
对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.从效 ...
- Django 源码小剖: Django 对象关系映射(ORM)
引 从前面已经知道, 一个 request 的到来和一个对应 response 的返回的流程, 数据处理和数据库离不开. 我们也经常在 views.py 的函数定义中与数据库打交道. django O ...
- 通过java反射实现简单的关于MongoDB的对象关系映射(ORM).
通过阅读MongoDB 3.2.1的官方文档中关于java 编程发现最新的文档并没有实现对对象到Document的映射,所以自己有了利用反射实现简单的关系映射. 1.定义抽象类:AbstractMo ...
- 对象-关系映射ORM(Object Relational Mapping)(转)
ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现 Hibernate在实现ORM功能的时候主要用到的文件有:映射类(*.java).映射文件(*.hbm.xml)和数据库配置文件 ...
- 对象关系映射 ORM
1.1 作用 MTV框架中包括一个重要的部分,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因 ...
- 对象关系映射(ORM)框架GreenDao简介和基本使用
官网上的介绍,greenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案. GreenDao特点 性能最大化,可能是Android平台上最快的ORM框架 易于使用的A ...
- Python学习---django之ORM语法[对象关系映射]180124
ORM语法[对象关系映射] ORM: 用面向对象的方式去操作数据库的创建表以及增删改查等操作. 优点:1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句.快速开发. 2 ...
- 对象关系映射(ORM)
1.什么是 对象-关系映射 对象-关系映射(Object Relational Mapping,简称ORM,对象关系映射)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,OR ...
随机推荐
- vue项目iframe的传值问题
前言 项目需要,我需要引入一个已经封装好的浏览器插件.插件只能以html的方式调用, 所以.我把插件的使用封装了一个html页面.vue项目则利用iframe的方式引入. 到这里我就遇到了一个问题,那 ...
- window,sts安装python
1.先在python官网下载最新的python安装,安装的时候勾上所有选项 官网:https://www.python.org/downloads/ 2.在sts里安装pyDev插件,我当时直接sea ...
- hdu 1817 Necklace of Beads (polya)
Necklace of Beads Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- codeblocks 调试
codeblocks 调试工具使用的注意事项: 1.codebloccks 调试,必须要在一个项目下才可以,也就是说“单独的文件是不能运行debug工具的” 2.项目的目录文件名必须是全英文,同时文件 ...
- 【编程题与分析题】Javascript 之继承的多种实现方式和优缺点总结
[!NOTE] 能熟练掌握每种继承方式的手写实现,并知道该继承实现方式的优缺点. 原型链继承 function Parent() { this.name = 'zhangsan'; this.chil ...
- linux与Windows进程控制
进程管理控制 这里实现的是一个自定义timer用于统计子进程运行的时间.使用方式主要是 timer [-t seconds] command arguments 例如要统计ls的运行时间可以直接输入t ...
- SpringSecurity退出功能实现的正确方式
本文将介绍在Spring Security框架下如何实现用户的"退出"logout的功能.其实这是一个非常简单的功能,我见过很多的程序员在使用了Spring Security之后, ...
- uniapp打包Android APP
1.uniAPP 将项目打包成,打包成功后格式如下 2.下载相关工具 Android studio(打包成app的工具) 和Hbuilder官方SDK,安装解压响应工具 3. 用 Android st ...
- 以太网驱动的流程浅析(一)-Ifconfig主要流程【原创】
以太网驱动的流程浅析(一)-Ifconfig主要流程 Author:张昺华 Email:920052390@qq.com Time:2019年3月23日星期六 此文也在我的个人公众号以及<Lin ...
- 【Luogu P2563】【集训Day 4 动态规划】质数和分解
题目链接:Luogu P2563 质数和分解(prime) [问题描述] 任何大于 1 的自然数 N,都可以写成若干个大于等于2且小于等于 N 的质数之和表达式(包括只有一个数构成的和表达式的情况), ...