Python实现ORM

Python实现ORM

ORM全称Object-Relational Mapping,简单的理解就是通过代码的方式操作数据库。ORM 的出现让我们不用关心 SQL 而用自己熟悉的编程语言来操作数据库。在Python开发中,ORM框架也是非常常见的,比如Django自带的ORM,SQLAlchemy等。

ORM的基本概念

建立连接

在使用ORM之前,需要首先建立与数据库的连接。可以使用Python的标准库sqlite3进行测试。

import sqlite3

# 连接数据库
conn = sqlite3.connect('test.db')
print('Opened database successfully')

定义模型

在使用ORM时,需要先定义模型。模型是一个面向对象的类,对应数据库中的一张表。类中的属性对应着表中的列。很多ORM框架都支持简便的语法来定义模型,比如Django的models.py文件。

class User:
    def __init__(self, id, name, age):
        self.id = id
        self.name = name
        self.age = age

操作数据库

ORM提供了常用的CRUD操作(Create、Read、Update、Delete)。

创建表

需要为模型创建对应的数据库表。

c.execute('''CREATE TABLE USER
       (ID INT PRIMARY KEY     NOT NULL,
       NAME           TEXT    NOT NULL,
       AGE            INT     NOT NULL);''')

插入数据

可以通过ORM向表中插入数据。

user = User(1, 'Alice', 18)
conn.execute("INSERT INTO USER (ID,NAME,AGE) \
      VALUES (?, ?, ?)", (user.id, user.name, user.age))

查询数据

可以通过属性来查询数据。

cursor = conn.execute("SELECT id, name, age from USER")
for row in cursor:
  user = User(row[0], row[1], row[2])
  print(f"ID = {user.id}, NAME = {user.name}, AGE = {user.age}")

更新数据

可以修改已有的数据。

user.age = 20
conn.execute("UPDATE USER set AGE = ? where ID = ?", (user.age, user.id))

删除数据

可以删除指定的数据。

conn.execute("DELETE from USER where ID = ?", (user.id,))

实现ORM的基本框架

ORM的实现思路:

  1. 将每个类定义为python类,类中的属性对应着表中的列
  2. 定义一个基础的Model类,所有的类继承这个类
  3. 在基础的Model类中为类动态的添加增、删、改、查四个方法

下面我们来实现这个框架。

类的映射

我们可以为每一个表定义对应的类。

class User(Model):
    __table__ = 'USER'

    id = IntegerField('ID', primary_key=True)
    name = StringField('NAME')
    age = IntegerField('AGE')

其中,__table__表示对应的表名,__primary_key__表示主键,IntegerField和StringField是两个常用的属性类型。

创建连接

import sqlite3

conn = sqlite3.connect('test.db')

Field类

我们可以将每个字段抽象成一个类,包括字符型、数值型等不同的类型。

class Field:
    pass

class StringField(Field):
    def __init__(self, name):
        self.name = name

class IntegerField(Field):
    def __init__(self, name):
        self.name = name

Model类 & 增删改查

在基础的Model类中为类动态的添加新增、删除、查询和更新四个方法。

class Model:
    @classmethod
    def create_table(cls):
        fields = []
        for k, v in cls.__dict__.items():
            if isinstance(v, Field) and v.primary_key is True:
                field = k + " " + v.field_type + " PRIMARY KEY"
                fields.append(field)
            elif isinstance(v, Field):
                field = k + " " + v.field_type
                fields.append(field)
        field_str = ", ".join(fields)
        table_name = cls.__table__
        create_sql = f"CREATE TABLE {table_name} ({field_str})"
        conn.execute(create_sql)

    def save(self):
        fields = []
        values = []
        for k, v in self.__dict__.items():
            if isinstance(v, Field) and v.primary_key is not True:
                fields.append(k)
                values.append(v)
        field_str = ", ".join(fields)
        value_str = ", ".join(["?" for _ in range(len(fields))])
        table_name = self.__table__
        insert_sql = f"INSERT INTO {table_name} ({field_str}) VALUES ({value_str})"
        conn.execute(insert_sql, values)
        conn.commit()

    @classmethod
    def get_one(cls, pk):
        table_name = cls.__table__
        pk_field = None
        for k, v in cls.__dict__.items():
            if isinstance(v, Field) and v.primary_key is True:
                pk_field = k
        select_sql = f"SELECT * FROM {table_name} WHERE {pk_field}=?"
        cursor = conn.execute(select_sql, (pk, ))
        row = cursor.fetchone()
        if row is None:
            return None
        values = [row[i] for i in range(len(row))]
        obj = cls()
        for k, v in obj.__dict__.items():
            if isinstance(v, Field) and v.primary_key is True:
                setattr(obj, k, values.pop(0))
            elif isinstance(v, Field):
                setattr(obj, k, values.pop(0))
        return obj

    def update(self):
        fields = []
        values = []
        pk_field = None
        for k, v in self.__dict__.items():
            if isinstance(v, Field) and v.primary_key is not True:
                fields.append(k + "=?")
                values.append(v)
            elif isinstance(v, Field) and v.primary_key is True:
                pk_field = k
        values.append(getattr(self, pk_field))
        field_str = ", ".join(fields)
        table_name = self.__table__
        update_sql = f"UPDATE {table_name} SET {field_str} WHERE {pk_field}=?"
        conn.execute(update_sql, values)
        conn.commit()

    def delete(self):
        pk_field_name = None
        for k, v in self.__dict__.items():
            if isinstance(v, Field) and v.primary_key is True:
                pk_field_name = k
        pk_val = getattr(self, pk_field_name)
        table_name = self.__table__
        delete_sql = f"DELETE FROM {table_name} WHERE {pk_field_name}=?"
        conn.execute(delete_sql, (pk_val, ))
        conn.commit()

在使用的时候,可以通过继承Model类来实现增删改查的功能。

class User(Model):
    __table__ = 'USER'
    id = IntegerField('ID', primary_key=True)
    name = StringField('NAME')
    age = IntegerField('AGE')

    def __init__(self, id, name, age):
        self.id = id
        self.name = name
        self.age = age

User.create_table()

user1 = User(1, 'Alice', 18)
user2 = User(2, 'Bob', 20)
user3 = User(3, 'Cindy', 22)

# 插入
user1.save()
user2.save()
user3.save()

# 查询
user = User.get_one(1)
print(f"id: {user.id}, name: {user.name}, age: {user.age}")

# 更新
user.age = 20
user.update()

# 删除
user.delete()

总结

ORM是非常常用的技术,比如在Django、Flask、SQLAlchemy等框架中都有非常完善的ORM。实现一个简单的ORM可以帮助我们更好的理解ORM的底层实现原理,从而更好地应对一些较为复杂的业务场景。

阅读剩余 81%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python实现ORM - Python技术站

(0)
上一篇 2023年3月28日
下一篇 2023年3月28日

相关文章

  • C语言详细分析不同类型数据在内存中的存储

    C语言详细分析不同类型数据在内存中的存储 在C语言中,不同类型的数据在内存中的存储方式是不同的。了解这些存储方式对于理解C语言的内存管理和数据操作非常重要。下面将详细讲解不同类型数据在内存中的存储方式,并提供两个示例说明。 1. 基本数据类型的存储 整型数据 整型数据在内存中的存储方式取决于其大小和符号性质。C语言提供了不同大小的整型数据类型,如char、s…

    other 2023年8月2日
    00
  • Mysql账号管理与引擎相关功能实现流程

    MySQL是一种关系型数据库管理系统,是很多网站和应用程序后台的首选数据库系统之一。MySQL账号管理和引擎相关功能对确保MySQL数据库的安全性有着至关重要的作用。下面,我将详细讲解MySQL账号管理和引擎相关功能的实现流程。 Mysql账号管理 创建新用户 要创建一个新用户,可以使用以下语句: CREATE USER ‘newuser’@’localho…

    other 2023年6月27日
    00
  • MySQL表的创建及字段介绍(小白入门篇)

    MySQL表的创建及字段介绍(小白入门篇) MySQL是一个广泛使用的关系型数据库管理系统,学习如何创建表及字段是MySQL的基础部分。在本文中,我们将介绍MySQL表的创建及字段的基本概念。 创建MySQL表的步骤 创建MySQL表的过程通常包括以下几个步骤: 选择一个合适的数据库来创建表。 设计表的结构:定义表的列,设置每一列的属性。 创建表:使用CRE…

    other 2023年6月25日
    00
  • Android调用外置摄像头的方法

    Android调用外置摄像头的方法攻略 在Android平台上,调用外置摄像头可以通过以下步骤完成: 确定权限:首先,需要在AndroidManifest.xml文件中添加相机权限。在<manifest>标签内添加以下代码: <uses-permission android:name=\"android.permission.CA…

    other 2023年8月21日
    00
  • 一步一步封装自己的HtmlHelper组件BootstrapHelper(二)

    我来为你详细讲解“一步一步封装自己的HtmlHelper组件BootstrapHelper(二)”的完整攻略。 标题 本攻略总共包含以下几个标题:- 引用相关类库- 封装组件方法- 示例1:使用BootstrapHelper生成表单- 示例2:使用BootstrapHelper生成面板 引用相关类库 在开始封装组件之前,我们需要引用Bootstrap相关类库…

    other 2023年6月25日
    00
  • 一文读懂Android Kotlin的数据流

    下面我来详细讲解“一文读懂Android Kotlin的数据流”的完整攻略。 一、数据流介绍 在Android应用开发中,数据流描述了从数据源到视图的数据传输过程,这个过程涉及到很多组件和框架,比如ViewModel、LiveData等。这些组件和框架可以帮助我们更方便地实现数据在应用中的传输和操作。 二、Kotlin中的数据流 在Kotlin中,我们可以使…

    other 2023年6月26日
    00
  • Mybatis中的config.xml配置文件详细解析

    Mybatis是一款非常流行的ORM框架,它的核心思想是将数据库操作映射成为Java方法,让开发者可以更加专注于业务逻辑的实现。而Mybatis的配置文件config.xml则是整个框架的重要组成部分,本文将对其进行一一讲解。 整体结构 Mybatis的config.xml配置文件整体结构非常简洁,分为configuration、properties、typ…

    other 2023年6月25日
    00
  • iOS8.1.1正式版固件下载地址 iOS 8.1.1正式版(12B436/435)固件官方下载大全

    iOS 8.1.1正式版固件下载地址 iOS 8.1.1正式版固件是苹果公司发布的操作系统固件版本,提供了一些修复和改进。以下是获取iOS 8.1.1正式版固件的详细攻略。 步骤一:访问官方网站 首先,你需要访问苹果公司的官方网站以获取iOS 8.1.1正式版固件的下载地址。你可以在以下网址找到官方下载页面:https://www.apple.com/ios…

    other 2023年8月5日
    00
合作推广
合作推广
分享本页
返回顶部