手撸系列之——ORM(对象关系映射)

ORM:对象关系映射
类               》》》     数据库的一张表
对象             》》》     表的一条记录
对象点属性        》》》     记录某一个字段对应的值

废话不多少,先上代码:

# orm.py

from mysql_singletion import Mysql

# 设置表字段类,通常需要的属性为字段名,字段类型,是否为主键,默认值
class Field(object):
    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

# 定义varchar类型字段类,设置默认值,方便调用
class StringField(Field):
    def __init__(self, name, column_type="varchar(32)", primary_key=False, default=None):
        super().__init__(name, column_type, primary_key, default)

# 定义int类型字段类
class IntegerField(Field):
    def __init__(self, name, column_type="int", primary_key=False, default=0):
        super().__init__(name, column_type, primary_key, default)

# 自定义元类,用来拦截模型表的创建过程(也可使用__init__方法拦截)
class MyMetaClass(type):
    def __new__(cls, cls_name, cls_bases, cls_attrs):
        # models不是模型表,因此不需要拦截其产生过程,直接调用type类的__new__方法产生models类并返回结果
        if cls_name == "Models":
            return type.__new__(cls, cls_name, cls_bases, cls_attrs)

        # 拦截模型表的闯将过程,使其增加table_name,primary_key及mappings(字段信息)的属性
        table_name = cls_attrs.get("table_name",cls_name.lower())
        primary_key = None
        mappings = {}

        #下面的for循环首先是将表的所有字段属性整合到mappings这个字典中,并确定主键字段
        for k,v in cls_attrs.items():
            # 取出表中所有由Field类产生的字段属性
            if isinstance(v,Field):
                mappings[k] = v
                if v.primary_key:
                    if primary_key:
                        raise TypeError("一张表只能有一个主键!")
                    primary_key = v.name
        # 由于已经将所有的字段属性添加到mappings中,需要将cls_attrs中的单个单个的字段属性删除
        for k in mappings.keys():
            cls_attrs.pop(k)
        # 检验表中最终是否有主键,如没有则报错,因为一个innodb引擎的mysql表有且只有一个主键
        if not primary_key:
            raise TypeError("一张表必须要有主键!")

        # 将下面三个属性添加至表的名称空间
        cls_attrs["table_name"] = table_name
        cls_attrs["primary_key"] = primary_key
        cls_attrs["mappings"] = mappings
        # 调用type类的__new__方法产生表那个类并返回
        return type.__new__(cls,cls_name,cls_bases,cls_attrs)

class Models(dict,metaclass=MyMetaClass):
    # __init__可以不写,最终也是直接调用dict类中的__init__方法去实例化,得到一个字典
    def __init__(self,**kwargs):
        super().__init__(**kwargs)

    # 由于继承字典类,对象无法直接点属性得到对应的属性值,__getatter__在对象点 不存在的属性 时触发,
    # 返回对象(也就是那个字典)属性(也就是字典中的key)对应的值,若字典中无该key则返回一个默认值。
    def __getattr__(self, item):
        return self.get(item,"没有该键!")

    # 使对象点属性设置或修改值的时候,能在对象(字典)中添加或修改其对应的key,value
    def __setattr__(self, key, value):
        self[key] = value

    # 类方法,表类调用进行数据的查操作
    @classmethod
    def select(cls, **kwargs):
        # 若每次查询都实例化一次Mysql的对象,那么当成千上万的用户访问服务器时压力太大,因此在此使用单例
        ms = Mysql.singletion()
        if not kwargs:
            sql = "select * from %s"%cls.table_name
            res = ms.select(sql)
        else:
            # 规定sql语句只能有一个查询条件,在此使用python代码对传入的参数进行限制,只取第一对参数进行查询
            k = list(kwargs.keys())[0]
            v = kwargs.get(k)
            # 这里的?就是一个纯粹的占位符,若一起使用%s则必须传值,因此先用?占位然后再用%s进行替换
            sql = "select * from %s where %s=?"%(cls.table_name,k)
            sql = sql.replace("?","%s")
            res = ms.select(sql,v)
        if res:
            # 下面这句代码可以说是orm的精髓,把查询出来的一条条记录再实例化成对象返回
            # res = [{},{},{}]
            # cls(name='...',password='...')
            return [cls(**r) for r in res]

if __name__ == '__main__':
    class Teacher(Models):
        table_name = "teacher"
        tid = IntegerField(name="tid",primary_key=True)
        tname = StringField(name="tname")
        age = IntegerField(name="age")

    t1 = Teacher(tid=1, tname="jason", age=18)
    print(t1.tid,t1.tname)
    print(Teacher.table_name)
    print(Teacher.primary_key)
    print(Teacher.mappings)
    print(Teacher.select(tname="李平老师"))

'''
    1  jason
    teacher
    id
    {'id': <__main__.IntegerField object at 0x000001BBCF4DD630>, 'name':        <__main__.StringField object at 0x000001BBCF4DDA20>}
    [{'tid': 2, 'tname': '李平老师'}]
'''
# mysql_singletion.py

 pymysql

class Mysql(object):
    __instance = None

    def __init__(self):
        self.conn = pymysql.connect(
            host="127.0.0.1",
            port=3306,
            user="root",
            password="",
            database="day41",
            charset="utf8",
            autocommit=True,
        )
        self.cursor = self.conn.cursor(pymysql.cursors.DictCursor)

    def close_db(self):
        self.cursor.close()
        self.conn.close()

    # 查找功能,传入sql代码及相应的关键参数
    def select(self, sql, args=None):
        self.cursor.execute(sql, args)
        # 返回的结果是一个列表中包含一系列的字典,每一个字典对应数据库中的一条记录
        res = self.cursor.fetchall()
        return res

    # 插入及修改数据功能
    def execute(self, sql, args):
        try:
            self.cursor.execute(sql, args)
        except BaseException as e:
            print(e)

    # 单例,使外界调用时只需实例化一个对象即可
    @classmethod
    def singletion(cls):
        if not Mysql.__instance:
            cls.__instance = cls()
        return cls.__instance

需要留意的几点:

原文地址:https://www.cnblogs.com/penghengshan/p/10896342.html

时间: 2024-08-20 12:08:11

手撸系列之——ORM(对象关系映射)的相关文章

ORM : 对象关系映射

ORM 对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”.

ORM对象关系映射

最近开发数据采集模块,数据解析完成之后,插入到数据库中的内存表,原来的同事留下的代码中,出现了大量SQL命令,调用了MySQL的客户端API,整个代码看出来乱乱的,程序效率也不高.很佩服这个同事的精神,使用了这么多的代码,加上很多SQL命令. 为了改进这个模块的设计,提高程序运行效率,查阅了大量的资料后,发现ORM对象关系映射解决了这个问题,避免使用大量的SQL命令,解决了类与数据库的耦合问题.本质就是人家C++高手写好的数据库方便操作的API,不用使用SQL命令,解决数据库存增删改查. 什么是

第54篇ORM对象关系映射 如何使用ORM与数据可建立连接

1. ORM(对象关系映射) 很多语言的很多web框架中都有这个概念 2. 为什么要有ORM? 1. 写程序离不开数据. 2. 在Python程序中要用到数据库中的数据,怎么办? 1. 使用pymysql连接MySQL数据库的步骤 1. import pymysql 2. 建立连接 conn = pymysql.connect( host='127.0.0.1', port=3306, database='day43', user='root', password='123', charset=

Php ORM 对象关系映射

ORM的全称是Object Relational Mapping,即对象关系映射.它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将这些对象组织起来,实现系统业务逻辑的过程.在ORM过程中最重要的概念是映射(Mapping),通过这种映射可以使业务对象与数据库分离.从面向对象来说,数据库不应该和业务逻辑绑定到一起,ORM则起到这样的分离作用,使数据库层透明,开发人员真正的面向对象.图 1简单说明了ORM在多层系统架构中的这个作用

44 MySQL &amp; orm对象关系映射

orm 模型 对象关系映射: Object Relational Mapping 是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 ORM模型的简单性简化了数据库查询过程 三个核心原则: 简单性:以最基本的形式建模数据:简化了数据库查询过程 传达性:数据库结构被任何人都能理解的语言文档化: 精确性:基于数据模型创建正确标准化的结构. 1)singleton 实现orm mysql_singleton.py import pymysql class Mysql(object)

ORM对象关系映射框架基本搭建

一 概念 1 概念 ORM :对象关系映射,对象和关系之间的映射,使用面向对象的方式来操作数据库 关系对象模型和python对象模型之间的映射 tabel => class ,表映射类 row => object ,行映射为实例 column=> property ,字段映射属性 2 举例 表有login,字段为id int , username varchar, age int 映射到python为 #!/usr/bin/poython3.6 #conding:utf-8 class

Android ORM对象关系映射之GreenDAO建立多表关联

https://blog.csdn.net/u010687392/article/details/48496299 利用GreenDAO可以非常方便的建立多张表之间的关联 一对一关联 通常我们在操作数据库的时候,我们往往不是单独的对一张表进行操作,而是对这张表的操作会联动的影响另外一张表或者多张表,比如:现在有两张表,一张是用户User表(有name.age.sex三个字段),一张是头像Picture表(有pictureId.pictureName.width.height四个字段).假如用户表

ORM即 对象-关系映射(转自:微冷的雨)

ORM即 对象-关系映射: 将数据库中的数据关系表,映射为实体对象. 灵动思绪EF(Entity FrameWork) 作者: 微冷的雨  来源: 博客园  发布时间: 2013-01-22 16:28  阅读: 10119 次  推荐: 16   原文链接   [收藏] 很久之前就想写这篇文章了,但是由于种种原因,没有将自己学习的EF知识整理成一片文章.今天我就用CodeFirst和ModelFirst两种方式的简单案例将自己学习的EF知识做个总结. 在讲解EF之前,我们先来看下ORM ORM

Android数据库框架——ORMLite轻量级的对象关系映射(ORM)Java包

Android数据库框架--ORMLite轻量级的对象关系映射(ORM)Java包 事实上,我想写数据库的念头已经很久了,在之前写了一个答题系统的小项目那只是初步的带了一下数据库,数据库是比较强大的,不是我们三言两语就能解决的,我一直想抽个时间自己再过一遍Sqlite和JDBC的,但是,大家也知道,琐事比较多,我们来说一下数据库的框架吧,事实上市面上,我觉得还可以的数据库框架有两个,ORMLite和GreenDao,我以前做的运动类的应用上,就需要存储大量的运动数据,我们最开始是在本地写数据库的