python-27-Python ORM系列之彻底搞明白ORM概念,对ORM进行封装结合FastAPI实现数据库的增删改查,联表查询等接口

python-27-Python ORM系列之彻底搞明白ORM概念,对ORM进行封装结合FastAPI实现数据库的增删改查,联表查询等接口

一.简介

在Python基础系列ORM部分为大家介绍了如何搭建MySQL数据和MySQL一些访问配置,同时也介绍了pymysql库的封装来实现对数据库的增删改查功能,但是截止以上都没有实现ORM,好菜已经上来 这一篇文章来帮助大家彻底掌握ORM框架,并且对ORM进行封装,利用ORM和FASTAPI实现数据库的增删改查,开始我们今天的日拱一卒!

二.安装pymysql、sqlalchemy、fastapi、uvicorn

#使用豆瓣源安装 提升安装速度
pip install pymysql -i http://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com
pip install sqlalchemy -i http://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com
pip install fastapi -i http://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com
pip install uvicorn -i http://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com

pymysql:Python 实现的 MySQL 数据库连接库

本文示例是调用MySql数据库,如果需要切换其他数据库,可以下载对应插件和改变ORM对应的连接字符串即可

MySQL-Python
mysql+mysqldb://:@[:]/

pymysql
mysql+pymysql://:@/[?]

MySQL-Connector
mysql+mysqlconnector://:@[:]/

cx_Oracle
oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value…]

SQLAlchemy:Python ORM(对象关系映射)工具

fastapi:FastAPI 是一个现代的、快速的 web 框架,用于构建 API

Uvicorn:Uvicorn 是一个高性能的 ASGI 服务器,适用于运行 FastAPI 和其他支持 ASGI 的 Python web 框架。

三.ORM基础介绍

1.首先我们需要sqlalchemy 多个不同模块和库,常用的引入如下

from sqlalchemy import create_engine,Column, Integer, String, ForeignKey,DateTime,Boolean,Text
from sqlalchemy.ext.declarative import declarative_base #orm基类
from sqlalchemy.orm import sessionmaker,relationship,joinedload

create_engine:创建数据库连接引擎。

Column, Integer, String, ForeignKey, DateTime, Boolean, Text:用来定义数据库表的字段类型和约束。

declarative_base:创建 ORM 基类,供模型类继承。

sessionmaker:创建数据库会话,执行数据库操作。

relationship:定义表之间的关系。

joinedload:优化查询,避免 N+1 查询问题。

四.构建数据库连接字符串的配置文件

4.1创建配置文件db_config.ini

在当前项目中创建config文件夹,在文件夹下db_config.ini文件,作为我们的数据库配置文件,内容如下:

[localdb]
host     = localhost
user     = root
password = yourpsw
port     = 3306
database = myurlhub

4.2创建获取配置文件工具包

在当前项目中创建utils文件夹,新建__init__.py文件,里面不用写任何东西,在utils文件夹下新建config_helper.py文件,用来帮助我们获取配置文件信息,文件内容如下:

import configparser

class Config(object):
    def __init__(self, filename, encoding='UTF-8'):
        # 声明配置类对象
        self.config = configparser.ConfigParser()
        # 读取配置文件
        self.config.read(filename, encoding)

    def get_value(self, section, option):
        """获取 value"""
        value = self.config.get(section, option)
        return value
    def get_items(self, section):
        value = dict(self.config.items(section))
        return value
    
# 读取配置文件
# config.read(fileName, 'GBK')
# print(f"sections: {config.sections()}")
# print(f"options: {config.options('localdb')}")
# print(f"items: {config.items('localdb')}")

我们的整体结构文件:

在这里插入图片描述

五.读取配置文件数据 构建数据库连接引擎

在当前项目文件夹utils中 新建orm_helper.py文件作为 ORM 帮助类库,我们需要根据配置文件来构建连接字符串,从而创建我们的ORM据库连接引擎 engine = create_engine(mysql_conn_str)

orm_helper.py 目前的代码:

#orm_helper.py
from sqlalchemy import create_engine,Column, Integer, String, ForeignKey,DateTime,Boolean,Text
from sqlalchemy.ext.declarative import declarative_base #orm基类
from sqlalchemy.orm import sessionmaker,relationship,joinedload
from utils import config_helper
import os
from datetime import datetime
import uuid
'''
数据库连接拼接串语法:
'''
# 加载数据库配置
__config_file_path = os.path.join(os.getcwd(),'config\db_config.ini') 
__config = config_helper.Config(__config_file_path,'UTF-8')
__localdb = __config.get_items('localdb')
mysql_conn_str = f"mysql+pymysql://{__localdb['user']}:{__localdb['password']}@{__localdb['host']}:{__localdb['port']}/{__localdb['database']}"

engine = create_engine(mysql_conn_str)

六.创建 ORM 基类,公共基类,用来定义数据库表的字段类型和约束的类

创建ORM模型的基类,公共字段基类,用于一键生成数据库对应的表字段

  1. 实现ORM基类:后续用来定义数据库表的字段类型和约束的类都要继承ORM的基类

    我们本次 要创建2个数据库表 都要继承ORM Base基类CommonFieldsMixin公共字段类,CommonFieldsMixin公共字段类,所有表都有的字段,不需要额外实现,直接继承实现

    Base = declarative_base() 
    # 我们本次 要创建2个数据库表 都要继承ORM Base基类 CommonFieldsMixin为公共字段类,为所有表都有的字段,不需要额外实现
    # 创建用户表
    #class MUH_User(Base,CommonFieldsMixin):
        
    #创建用户登录密码表
    #class MUH_User_Psw(Base,CommonFieldsMixin):
    
  2. 实现与数据库关联的ORM表的类:这些类后续为ORM操作的对象,我们就可像操作对象一样操作这2个类与数据库进行关联,而不需要关心SQL实现

    因为我们需要实现用户注册,故要创建2张表 用户表 和 用户密码表,一张保存用户基础信息,一张保存用户密码表

    注意有几个细节:

    1. 创建公共基类CommonFieldsMixin,让所有的表都自动包含公共基类字段

      class MUH_User(Base,CommonFieldsMixin):
      class MUH_User_Psw(Base,CommonFieldsMixin)
      

      其中Base 是ORM基类 CommonFieldsMixin为公共基类

      ORM类定义说明:

      create_date = Column(DateTime, default=datetime.now())
      
      • create_date:对应数据库表的列名

      • Column:表示列

      • DateTime:数据类型,注意数据库表的类型都是基础类型,千万别搞个列表,字典,元组作为表的类型,如果非要用请转换为JSON string类型

      • default:默认值

      • ORM中常见类型约束及其他约束整理如下

        ORM表中列的类型说明举例
        Integer整数类型的字段age = Column(Integer)
        String(length)描述变长字符串类型的字段name = Column(String(50))
        Text用于存储较长文本description = Column(Text)
        Boolean描述布尔值类型的字段is_active = Column(Boolean, default=True)
        Float描述浮点数类型的字段price = Column(Float)
        Numeric(precision, scale)精确数字类型,适用于需要高精度的小数amount = Column(Numeric(10, 2)) #精度为 10 位,保留 2 位小数的数字
        Date描述日期类型字段,不包含时间部分birthdate = Column(Date)
        DateTime描述日期和时间类型字段created_at = Column(DateTime)
        Time描述时间类型字段,不包含日期部分clock_in = Column(Time)
        Interval描述时间间隔字段,用于存储持续时间(例如,2 days, 5 hours)duration = Column(Interval)
        UUID用于存储 UUID(通用唯一标识符)user_id = Column(UUID(as_uuid=True), default=uuid.uuid4)
        LargeBinary(不建议使用)描述二进制数据字段,适用于存储大块二进制数据,如文件或图像。image = Column(LargeBinary)
        Enum用于存储枚举类型字段,通常用于有限的固定选项(如性别、状态等)size = Column(Enum(‘small’, ‘medium’, ‘large’, name=‘size’))
        JSON用于存储 JSON 格式的数据preferences = Column(JSON)
        ForeignKey用于指定外键约束,表示该列是另一个表的外键user_id = Column(Integer, ForeignKey(‘users.id’))
        primary_key定义表的主键id = Column(String(50), primary_key=True, default=str(uuid.uuid4()))
        nullable是否可为nullname = Column(String(100), nullable=False)
        default默认值id = Column(String(50), primary_key=True, default=str(uuid.uuid4()))
        onupdate当更新默认值onupdate=datetime.utcnow

      创建公共基类

      #orm_helper.py
      #公共基类
      # 定义公共字段 Mixin 类
      class CommonFieldsMixin:
          create_date = Column(DateTime, default=datetime.now())
          create_id = Column(String(50))
          update_date = Column(DateTime, default=datetime.now(), onupdate=datetime.now)
          update_id = Column(String(50))
          visible = Column(Boolean, default=True)
          descriptions = Column(Text)
      
    2. 所有的id 采用guid字符串来实现,故引入import uuid

      默认自动生成id = Column(String(50), primary_key=True,default=uuid.uuid4())

      #orm_helper.py
      # 创建用户表
      class MUH_User(Base,CommonFieldsMixin):
          __tablename__ = "muh_user"
          id = Column(String(50), primary_key=True,default=str(uuid.uuid4()))
          user_name = Column(String(20))
          user_gender = Column(String(2))
          user_age = Column(Integer)
          user_imgs =Column(String(255))
          def __repr__(self):
              # 自动列出所有字段
              attrs = {column.name: getattr(self, column.name) for column in self.__table__.columns}
              return f"<{self.__class__.__name__}({', '.join(f'{key}={value!r}' for key, value in attrs.items())})>"
      
      #创建用户登录密码表
      class MUH_User_Psw(Base,CommonFieldsMixin):
          __tablename__ = "muh_user_psw"
          id = Column(String(50), primary_key=True,default=str(uuid.uuid4())) 
          user_id = Column(String(50))
          user_psw = Column(String(255))
          def __repr__(self):
              # 自动列出所有字段
              attrs = {column.name: getattr(self, column.name) for column in self.__table__.columns}
              return f"<{self.__class__.__name__}({', '.join(f'{key}={value!r}' for key, value in attrs.items())})>"
      
      
    3. def __repr__(self)是用来查询时候自动转换为对应类的实例,采用固定写法,大家照着写就行

      以下为def __repr__(self)的演变:

      #`def __repr__(self)`原本的实现方式
      #格式1:
          def __repr__(self):
              return f"<MUH_User(id='{self.id}', name='{self.name}', gender='{self.gender}', grade='{self.grade}', age='{self.age}', " \
                     f"user_img='{self.user_img}', create_date='{self.create_date}', create_id='{self.create_id}', " \
                     f"update_date='{self.update_date}', update_id='{self.update_id}', visible='{self.visible}', descriptions='{self.descriptions}')>"
      #格式2:            
          def __repr__(self):
              return "<MUH_User_Psw(id='%s', user_id='%s',user_psw='%s',carete_date='%s',carete_id='%s',update_date='%s',update_id='%s',visable='%s',descrptions='%s')>" % (self.id, self.user_id, self.user_psw, self.carete_date, self.carete_id, self.update_date,self.update_id,self.visable,self.descrptions)
      #格式3:
          def __repr__(self):
              # 自动列出所有字段
              attrs = {column.name: getattr(self, column.name) for column in self.__table__.columns}
              return f"<{self.__class__.__name__}({', '.join(f'{key}={value!r}' for key, value in attrs.items())})>"
      

七.创建 ORM 帮助类库

其实定义以上我们已经实现了ORM,但是好的程序员在使用前会创建自己的帮助类库

在orm_helper.py接着实现 ORM 帮助类库,代码如下:

#orm_helper.py

class OrmManager(object):

    def __init__(self):
        self.__make_session()

    def create_table(self):
        try:
            Base.metadata.create_all(engine)  #这个语句可以创建所有继承了Base的子类的orm数据库表
        except Exception as e:
            print(f"create_table has error with {e}")


    def __make_session(self):
        Session = sessionmaker(bind=engine)  #工厂模式,返回类
        self.__session = Session()

    def fetch_session(self):
        return self.__session

    def add_records(self, objs):
        """
        插入记录
        :param objs: [obj1, obj2] 或 单个 obj
        """
        try:
            if isinstance(objs, list):
                self.__session.add_all(objs)
            else:
                self.__session.add(objs)
            self.__session.commit()
        except Exception as e:
            self.__session.rollback()
            print(f"Error adding records: {e}")

    def delete_records(self, objs):
        """
        删除记录
        :param objs: [obj1, obj2] 或 单个 obj
        """
        try:
            if isinstance(objs, list):
                for item in objs:
                    self.__session.delete(item)
            else:
                self.__session.delete(objs)
            self.__session.commit()
        except Exception as e:
            self.__session.rollback()
            print(f"Error deleting records: {e}")

    def query_records(self, model_class, filters=None, **kwargs): #cls 表示传入类
        """
        查询记录
        :param model_class: ORM类模型
        :param filters: 过滤条件,字典形式
        :param kwargs: 其他查询条件,如分页,排序等
        :return: 查询结果


        :调用方式:# 查询名字为 'John' 的用户
                    filters = {'name': 'John'}
                    users = orm_manager.query_records(MUH_User, filters=filters)
                  
                    # 分页查询,第 2 页,每页 10 条记录
                    page = 2
                    per_page = 10
                    users = orm_manager.query_records(MUH_User, filters=None, offset=(page-1) * per_page, limit=per_page)
                    # 查询所有用户并按年龄升序排序
                    users = orm_manager.query_records(MUH_User, filters=None, order_by=[MUH_User.age])
                    # 查询性别为 'Male' 且年龄大于 30 的用户,按年龄降序排列,显示前 5 条记录
                    filters = {'gender': 'Male'}
                    users = orm_manager.query_records(MUH_User, filters=filters, age=30, order_by=[MUH_User.age.desc()], limit=5)
                    # 查询年龄为 25 或 30 的用户
                    filters = {'age': [25, 30]}
                    users = orm_manager.query_records(MUH_User, filters=filters)
                    # 查询 id 为 '123' 的用户及其密码
                    from sqlalchemy.orm import joinedload
                    users_with_psw = orm_manager.query_records(MUH_User, filters={'id': '123'}, join=MUH_User.password)
        """
        query = self.__session.query(model_class)
        if filters:
            query = query.filter_by(**filters)
        for key, value in kwargs.items():
            if hasattr(model_class, key):
                query = query.filter(getattr(model_class, key) == value)
        return query.all()
    def query(self, *cls):
        '''
        查询记录
        直接返回query
        '''
        if  cls :
            return self.__session.query(*cls)
        else:
            return []

说明:

  1. self.__make_session(),用来创建orm的session,这个就是ORM用来操作数据库的session 很重要
    def __make_session(self):
        Session = sessionmaker(bind=engine)  #工厂模式,返回类
        self.__session = Session()
  1. 为了让我们的帮助类库更灵活,我们通过fetch_session 来返回session,方便我们以ORM原始方式来操作
    def fetch_session(self):
        return self.__session
  1. 增删查方法

    def add_records(self, objs):新增数据方法

    def delete_records(self, objs):删除方法

    def query_records:查询方法

  2. 为了让我们的查询更灵活,我们定义查询基本方法def query(self, *cls),方便我们以ORM原始方式来操作

  3. 一键生成数据库中的表函数

        def create_table(self):
            try:
                Base.metadata.create_all(engine)  #这个语句可以创建所有继承了Base的子类的orm数据库表
            except Exception as e:
                print(f"create_table has error with {e}")
    

八.orm_helper.py完整代码:

#orm_helper.py
from sqlalchemy import create_engine,Column, Integer, String, ForeignKey,DateTime,Boolean,Text
from sqlalchemy.ext.declarative import declarative_base #orm基类
from sqlalchemy.orm import sessionmaker,relationship,joinedload
from utils import config_helper
import os
from datetime import datetime
import uuid
'''
数据库连接拼接串语法:
'''
# 加载数据库配置
__config_file_path = os.path.join(os.getcwd(),'config\db_config.ini') 
__config = config_helper.Config(__config_file_path,'UTF-8')
__localdb = __config.get_items('localdb')
mysql_conn_str = f"mysql+pymysql://{__localdb['user']}:{__localdb['password']}@{__localdb['host']}:{__localdb['port']}/{__localdb['database']}"

engine = create_engine(mysql_conn_str)
Base = declarative_base()

#公共基类
# 定义公共字段 Mixin 类
class CommonFieldsMixin:
    create_at = Column(DateTime, default=datetime.now())
    create_id = Column(String(50))
    update_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now)
    update_id = Column(String(50))
    visible = Column(Boolean, default=True)
    descriptions = Column(Text)
# 创建用户表
class MUH_User(Base,CommonFieldsMixin):
    __tablename__ = "muh_user"
    id = Column(String(50), primary_key=True,default=str(uuid.uuid4()))
    user_name = Column(String(20))
    user_gender = Column(String(2))
    user_age = Column(Integer)
    user_imgs =Column(String(255))
    def __repr__(self):
        # 自动列出所有字段
        attrs = {column.name: getattr(self, column.name) for column in self.__table__.columns}
        return f"<{self.__class__.__name__}({', '.join(f'{key}={value!r}' for key, value in attrs.items())})>"

#创建用户登录密码表
class MUH_User_Psw(Base,CommonFieldsMixin):
    __tablename__ = "muh_user_psw"
    id = Column(String(50), primary_key=True,default=str(uuid.uuid4())) 
    user_id = Column(String(50))
    user_psw = Column(String(255))
    def __repr__(self):
        # 自动列出所有字段
        attrs = {column.name: getattr(self, column.name) for column in self.__table__.columns}
        return f"<{self.__class__.__name__}({', '.join(f'{key}={value!r}' for key, value in attrs.items())})>"




class OrmManager(object):

    def __init__(self):
        self.__make_session()

    def create_table(self):
        try:
            Base.metadata.create_all(engine)  #这个语句可以创建所有继承了Base的子类的orm数据库表
        except Exception as e:
            print(f"create_table has error with {e}")


    def __make_session(self):
        Session = sessionmaker(bind=engine)  #工厂模式,返回类
        self.__session = Session()

    def fetch_session(self):
        return self.__session

    def add_records(self, objs):
        """
        插入记录
        :param objs: [obj1, obj2] 或 单个 obj
        """
        try:
            if isinstance(objs, list):
                self.__session.add_all(objs)
            else:
                self.__session.add(objs)
            self.__session.commit()
        except Exception as e:
            self.__session.rollback()
            print(f"Error adding records: {e}")

    def delete_records(self, objs):
        """
        删除记录
        :param objs: [obj1, obj2] 或 单个 obj
        """
        try:
            if isinstance(objs, list):
                for item in objs:
                    self.__session.delete(item)
            else:
                self.__session.delete(objs)
            self.__session.commit()
        except Exception as e:
            self.__session.rollback()
            print(f"Error deleting records: {e}")

    def query_records(self, model_class, filters=None, **kwargs): #cls 表示传入类
        """
        查询记录
        :param model_class: ORM类模型
        :param filters: 过滤条件,字典形式
        :param kwargs: 其他查询条件,如分页,排序等
        :return: 查询结果


        :调用方式:# 查询名字为 'John' 的用户
                    filters = {'name': 'John'}
                    users = orm_manager.query_records(MUH_User, filters=filters)
                  
                    # 分页查询,第 2 页,每页 10 条记录
                    page = 2
                    per_page = 10
                    users = orm_manager.query_records(MUH_User, filters=None, offset=(page-1) * per_page, limit=per_page)
                    # 查询所有用户并按年龄升序排序
                    users = orm_manager.query_records(MUH_User, filters=None, order_by=[MUH_User.age])
                    # 查询性别为 'Male' 且年龄大于 30 的用户,按年龄降序排列,显示前 5 条记录
                    filters = {'gender': 'Male'}
                    users = orm_manager.query_records(MUH_User, filters=filters, age=30, order_by=[MUH_User.age.desc()], limit=5)
                    # 查询年龄为 25 或 30 的用户
                    filters = {'age': [25, 30]}
                    users = orm_manager.query_records(MUH_User, filters=filters)
                    # 查询 id 为 '123' 的用户及其密码
                    from sqlalchemy.orm import joinedload
                    users_with_psw = orm_manager.query_records(MUH_User, filters={'id': '123'}, join=MUH_User.password)
        """
        query = self.__session.query(model_class)
        if filters:
            query = query.filter_by(**filters)
        for key, value in kwargs.items():
            if hasattr(model_class, key):
                query = query.filter(getattr(model_class, key) == value)
        return query.all()
    def query(self, *cls):
        '''
        查询记录
        直接返回query
        '''
        if  cls :
            return self.__session.query(*cls)
        else:
            return []

项目结构:

在这里插入图片描述

九.使用ORM帮助类库,通过FastAPI接口方式实现

1.FastAPI的构建方式

下载依赖fastapi 、uvicorn

pip install fastapi uvicorn -i http://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com

2.FastAPI的基本创建API路由格式

from fastapi import FastAPI

app = FastAPI()  # 创建 FastAPI 应用实例

@app.get("/")
def read_root():
    return {"message": "Hello, World!"}

3.vscode 启动方式

vscode 终端—>新建终端 运行uvicorn main:app --reload --port 8081,当出现以下表示运行成功!端口可以自由切换

uvicorn main:app --reload --host 192.168.0.1 --port 8081

main:指定运行的文件名 main.py

app: 是 FastAPI 应用对象

reload: 是在代码修改后自动重载应用

host :服务器地址

port :指定端口号

(my_venv) PS F:\开发源码\python_demo_06> uvicorn main:app --reload --port 8081
INFO:     Will watch for changes in these directories: ['F:\\开发源码\\python_demo_06']
INFO:     Uvicorn running on http://127.0.0.1:8081 (Press CTRL+C to quit)
INFO:     Started reloader process [25572] using statreload
INFO:     Started server process [13932]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

FastAPI 会自动为你的 API 生成 Swagger UIReDoc 文档:

http://127.0.0.1:8081/docs

http://127.0.0.1:8081/redoc

  • 访问 http://127.0.0.1:8081/docs,你将看到 Swagger UI 文档。

在这里插入图片描述

  • 访问 http://127.0.0.1:8081/redoc,你将看到 ReDoc 文档。

在这里插入图片描述

十.FastAPI+ORM实现代码一键生成数据库中对应的表

  1. 一键生成数据库中对应的表

    # main.py
    from fastapi import FastAPI, HTTPException
    from pydantic import BaseModel
    from typing import List, Optional
    from utils import orm_helper as orm
    from datetime import datetime
    import uuid
    from sqlalchemy.orm import joinedload
    from sqlalchemy import join
    
    app = FastAPI()
    
    # 1. 创建表
    @app.get("/create_table")
    def create_table():
        db = orm.OrmManager()
        db.create_table()
        return {"code": 200, "success": "Tables created successfully", "data": ""}
    

直接直接调用http://127.0.0.1:8081/docs提供的API来调试我们的接口

在这里插入图片描述

执行后的数据库,可见我们的表和字段都创建成功!

在这里插入图片描述

十一.FastAPI+ORM实现新增用户和密码

代码如下:

# main.py
# 2. 新增用户和密码
class UserCreate(BaseModel):
    user_name: str
    user_gender: str
    user_age: int
    user_imgs: Optional[str] = None
    user_psw: str

@app.post("/create_user")
def create_user(user: UserCreate):
    db = orm.OrmManager()
    
    # 创建用户
    new_user = orm.MUH_User(
        id=str(uuid.uuid4()),
        user_name=user.user_name,
        user_gender=user.user_gender,      
        user_age=user.user_age,
        user_imgs=user.user_imgs
    )
    
    # 创建密码
    new_psw = orm.MUH_User_Psw(
        id=str(uuid.uuid4()),
        user_id=new_user.id,
        user_psw=user.user_psw
    )
    
    # 插入到数据库
    db.add_records([new_user, new_psw])
    
    return {"code": 200, "success": "User and password created successfully"}

调用接口:

在这里插入图片描述

数据库写入信息:

在这里插入图片描述

十二.查询用户信息

代码如下:

# main.py
# 3. 查询用户信息
@app.get("/get_user/{user_id}")
def get_user(user_id: str):
    db = orm.OrmManager()
    
    # 查询用户和密码
    user = db.query_records(orm.MUH_User, filters={"id": user_id})
    password = db.query_records(orm.MUH_User_Psw, filters={"user_id": user_id})
    
    if user and password:
        return {"user": user[0], "password": password[0].user_psw}
    else:
        raise HTTPException(status_code=404, detail="User not found")

查询结果:

在这里插入图片描述

十三.更新用户信息

代码如下:

# main.py
# 4. 更新用户信息
class UserUpdate(BaseModel):
    id:Optional[str] = None
    user_name: Optional[str] = None

@app.put("/update_user/{user_id}")
def update_user(user: UserUpdate):
    try:
        db = orm.OrmManager()
        session = db.fetch_session()
        user_to_update  = session.query(orm.MUH_User).filter_by(id = user.id).first()
        print(user_to_update )
        user_to_update .user_name = user.user_name
        if not user_to_update:
            raise HTTPException(status_code=404, detail="User not found")
        
        # 更新用户字段
        if user.user_name:
            user_to_update.name = user.user_name  # 修改用户的名称字段

        # 提交更改
        session.commit()
        return {"code": 200, "success": "User updated successfully"}
    except Exception as e:
        return {"code": 400, "error": f"User updated error{e}"}

调用FastAPI接口:

在这里插入图片描述

数据库修改结果:

在这里插入图片描述

十四.删除数据

代码如下

# main.py
# 5. 删除用户和密码
@app.delete("/delete_user/{user_id}")
def delete_user(user_id: str):
    db = orm.OrmManager()
    
    # 查询并删除用户和密码
    user = db.query_records(orm.MUH_User, filters={"id": user_id})
    password = db.query_records(orm.MUH_User_Psw, filters={"user_id": user_id})
    
    if not user or not password:
        raise HTTPException(status_code=404, detail="User not found")
    
    db.delete_records(user+password)  # 删除用户及其密码 +好为两个列表合并为一个列表
    return {"code": 200, "success": "User and password deleted successfully"}

调用FastAPI

在这里插入图片描述

数据库结果

在这里插入图片描述

十五.多表联合查询

代码如下:

# main.py
# 6.查询所有用户和密码
@app.get("/get_all_users_and_passwords")
def get_all_users_and_passwords():
    db = orm.OrmManager()

    # 联接查询,获取用户及其密码
    users_with_passwords = db.fetch_session().query(orm.MUH_User, orm.MUH_User_Psw).join(orm.MUH_User_Psw, orm.MUH_User.id == orm.MUH_User_Psw.user_id).all()

    if not users_with_passwords:
        raise HTTPException(status_code=404, detail="No users found")
    
    # 构建返回的数据
    result = []
    for user, password in users_with_passwords:
        result.append({
            "id": user.id,
            "user_name": user.user_name,
            "user_gender": user.user_gender,
            "user_age": user.user_age,
            "user_imgs": user.user_imgs,
            "user_psw": password.user_psw  
        })
    
    return {"code": 200, "success": "Users and passwords fetched successfully", "data": result}

调用FastAPI结果:

在这里插入图片描述

十六.完整的main.py代码

#main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
from utils import orm_helper as orm
from datetime import datetime
import uuid
from sqlalchemy.orm import joinedload
from sqlalchemy import join

app = FastAPI()

# 1. 创建表
@app.get("/create_table")
def create_table():
    db = orm.OrmManager()
    db.create_table()
    return {"code": 200, "success": "Tables created successfully", "data": ""}

# 2. 新增用户和密码
class UserCreate(BaseModel):
    user_name: str
    user_gender: str
    user_age: int
    user_imgs: Optional[str] = None
    user_psw: str

@app.post("/create_user")
def create_user(user: UserCreate):
    db = orm.OrmManager()
    
    # 创建用户
    new_user = orm.MUH_User(
        id=str(uuid.uuid4()),
        user_name=user.user_name,
        user_gender=user.user_gender,      
        user_age=user.user_age,
        user_imgs=user.user_imgs
    )
    
    # 创建密码
    new_psw = orm.MUH_User_Psw(
        id=str(uuid.uuid4()),
        user_id=new_user.id,
        user_psw=user.user_psw
    )
    
    # 插入到数据库
    db.add_records([new_user, new_psw])
    
    return {"code": 200, "success": "User and password created successfully"}

# 3. 查询用户信息
@app.get("/get_user/{user_id}")
def get_user(user_id: str):
    db = orm.OrmManager()
    
    # 查询用户和密码
    user = db.query_records(orm.MUH_User, filters={"id": user_id})
    password = db.query_records(orm.MUH_User_Psw, filters={"user_id": user_id})
    
    if user and password:
        return {"user": user[0], "password": password[0].user_psw}
    else:
        raise HTTPException(status_code=404, detail="User not found")

# 4. 更新用户信息
class UserUpdate(BaseModel):
    id:Optional[str] = None
    user_name: Optional[str] = None

@app.put("/update_user/{user_id}")
def update_user(user: UserUpdate):
    try:
        db = orm.OrmManager()
        session = db.fetch_session()
        user_to_update  = session.query(orm.MUH_User).filter_by(id = user.id).first()
        print(user_to_update )
        user_to_update .user_name = user.user_name
        if not user_to_update:
            raise HTTPException(status_code=404, detail="User not found")
        
        # 更新用户字段
        if user.user_name:
            user_to_update.name = user.user_name  # 修改用户的名称字段

        # 提交更改
        session.commit()
        return {"code": 200, "success": "User updated successfully"}
    except Exception as e:
        return {"code": 400, "error": f"User updated error{e}"}

# 5. 删除用户和密码
@app.delete("/delete_user/{user_id}")
def delete_user(user_id: str):
    db = orm.OrmManager()
    
    # 查询并删除用户和密码
    user = db.query_records(orm.MUH_User, filters={"id": user_id})
    password = db.query_records(orm.MUH_User_Psw, filters={"user_id": user_id})
    
    if not user or not password:
        raise HTTPException(status_code=404, detail="User not found")
    
    db.delete_records(user+password)  # 删除用户及其密码 +好为两个列表合并为一个列表
    return {"code": 200, "success": "User and password deleted successfully"}


# 6.查询所有用户和密码
@app.get("/get_all_users_and_passwords")
def get_all_users_and_passwords():
    db = orm.OrmManager()

    # 联接查询,获取用户及其密码
    users_with_passwords = db.fetch_session().query(orm.MUH_User, orm.MUH_User_Psw).join(orm.MUH_User_Psw, orm.MUH_User.id == orm.MUH_User_Psw.user_id).all()

    if not users_with_passwords:
        raise HTTPException(status_code=404, detail="No users found")
    
    # 构建返回的数据
    result = []
    for user, password in users_with_passwords:
        result.append({
            "id": user.id,
            "user_name": user.user_name,
            "user_gender": user.user_gender,
            "user_age": user.user_age,
            "user_imgs": user.user_imgs,
            "user_psw": password.user_psw  # 获取密码
        })
    
    return {"code": 200, "success": "Users and passwords fetched successfully", "data": result}

十七.总结

关于python ORM系列,从背景介绍,到数据库安装,到pymysql使用,到最终的ORM,一起写了好几个晚上,终于实现了ORM 让python操纵数据库像操作对象一样!

代码包 放到我的资源里面了,大家找找如果审核通过,应该可以下!

创作整理不易,请大家多多关注 多多点赞,有写的不对的地方欢迎大家补充,我来整理,再次感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SEEONTIME

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值