Python DAO层 数据库基类封装

目录

1.BaseEntity

2.t_user

3.DAOBase

4.UserDAO


刚开始用Python做Api后端,记录下学习过程

从数据库操作开始,定义实体,定义DAO层基类,及DAO业务类的使用

写的不好,有好的设计建议欢迎大家提出,一起学习进步

1.BaseEntity

这部分是实体的基类,比较简单,就一个使用类名作为表名的方法


from sqlalchemy import Column, Integer, DateTime, modifier
from sqlalchemy.orm import InstrumentedAttribute, properties
from sqlalchemy.sql import func
from sqlalchemy.ext.declarative import as_declarative, declared_attr



@as_declarative()
class BaseEntity:

    @declared_attr
    def __tablename__(cls) -> str:
        # 如果没有指定__tablename__  则默认使用model类名转换表名字
        return cls.__name__
    

2.t_user

用户数据表,实体定义,数据库操作的数据依据

这部分我也写了一个自动生成Entity的小应用程序,欢迎大家下载使用

https://download.csdn.net/download/rotion135/85124222

from sqlalchemy import Column, Integer, String,Boolean,DateTime,Double,Float
from Modules.db.BaseEntity import BaseEntity

#t_user
class t_user(BaseEntity):
    ID = Column(String(32), primary_key=True,nullable=False, comment="表ID")
    UserCode = Column(String(32), primary_key=False,nullable=False, comment="用户编码")
    UserName = Column(String(128), primary_key=False,nullable=False, comment="用户名称")
    LoginName = Column(String(128), primary_key=False,nullable=False, comment="登录名")
    Password = Column(String(255), primary_key=False,nullable=False, comment="登录密码")
    UserStatus = Column(Integer, primary_key=False,nullable=True, comment="用户状态  默认0:正常,1:禁用 可字典项配置")
    IsDelete = Column(Integer, primary_key=False,nullable=True, comment="删除为1,未删除为0,默认0")
    Nick = Column(String(128), primary_key=False,nullable=True, comment="昵称")
    Title = Column(String(128), primary_key=False,nullable=True, comment="职称")
    Sex = Column(Integer, primary_key=False,nullable=True, comment="性别 0:男;1:女")
    Birthday = Column(String(32), primary_key=False,nullable=True, comment="生日")
    IdentityCard = Column(String(128), primary_key=False,nullable=True, comment="身份证号码")
    Mobile = Column(String(32), primary_key=False,nullable=True, comment="手机号")
    Telephone = Column(String(32), primary_key=False,nullable=True, comment="电话号码")
    QQ = Column(String(32), primary_key=False,nullable=True, comment="QQ号")
    Email = Column(String(128), primary_key=False,nullable=True, comment="邮箱")
    Signature = Column(String(255), primary_key=False,nullable=True, comment="个性签名")
    IsAdmin = Column(Integer, primary_key=False,nullable=True, comment="是否管理员  0-非管理员 1-管理员")
    CreateTime = Column(DateTime, primary_key=False,nullable=True, comment="创建时间")
    CreateUserCode = Column(String(32), primary_key=False,nullable=True, comment="创建人的用户编码")
    ModifyTime = Column(DateTime, primary_key=False,nullable=True, comment="修改时间")
    ModifyUserCode = Column(String(32), primary_key=False,nullable=True, comment="修改人的用户编码,只保存最后一次修改人")
    Remark = Column(String, primary_key=False,nullable=True, comment="备注")
    Token = Column(String(32), primary_key=False,nullable=True, comment="访问令牌")
    TokenExTime = Column(DateTime, primary_key=False,nullable=True, comment="访问令牌过期时间")
    RefreshToken = Column(String(32), primary_key=False,nullable=True, comment="刷新令牌")
    RefreshExTime = Column(DateTime, primary_key=False,nullable=True, comment="刷新令牌过期时间")

    

3.DAOBase

接下来就是设计DAO层的基类

数据链接 我用了Config.py作为配置文件,在下面一个代码块里边

from sqlalchemy import create_engine, Column, Integer, String,Engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker,Session
from Modules.SysFrame import Config


class DAOBase():
    def __init__(self,db:Session=None):
        if(db==None):
            self.__InitEngine()
        else :
            self.session=db
        
        

    engine:Engine
    session:Session


    def __InitEngine(self):
        # 创建一个引擎来连接到 MySQL 数据库
        self.engine = create_engine(Config.MySQLConnection)
        # 创建一个会话类
        sm = sessionmaker(autocommit=False, autoflush=False, bind=self.engine)
        self.session = sm()

    

    




cors_allowOrigins="*"
#后台自定义的请求头参数
cors_allowHeaders="Origin,Accept,Accept-Language,Authorization,Content-Type,UserCode,Timestamp,Nonce,Signature"
#请求后台允许的方式
cors_allowMethods="GET, POST, PUT, DELETE, OPTIONS"
#登录限制时间,时间内登录次数超过设置值,则锁定
LoginLimitMinutes=60
#登录限制时间内的登陆错误次数限制
LoginLimitCount=5


#MySQL数据库连接字符串
# 格式为:'数据库类型+数据库驱动名称://用户名:密码@主机地址:端口号/数据库名称'
MySQLConnection="mysql+mysqlconnector://root:123qwe@127.0.0.1:3306/platform"





4.UserDAO

最后,展示用户操作类的视线

BaseResult 是我自己定义的一个结果类,也放在下面代码块了



from datetime import datetime
from sqlalchemy import func,text
from sqlalchemy.orm import sessionmaker
from Modules.Models.BaseResult import BaseResult
from Modules.db.DAOBase import DAOBase
from Modules.db.Entity.t_user import t_user

class UserDAO(DAOBase):
    def __init__(self, db: sessionmaker = None):
        super().__init__(db)

    # 根据用户编码获取用户数据        
    def GetUserByUserCode(self,userCode:str)->t_user:
        sql =  self.session.query(t_user).filter(t_user.UserCode==userCode).first()
        return sql;
        

    # 根据登录名获取用户数据
    def  GetUserByLogin(self,loginName:str)->t_user:
        sql = self.session.query(t_user).filter(t_user.LoginName==loginName).first()
        return sql;


    # 新增前检测 true-正常,可新增 false-已存在相同数据
    def  CheckBeforeInsert(self,userCode:str)->BaseResult:
        row_count = self.session.query(func.count(t_user.ID)).filter(t_user.UserCode==userCode).scalar()
        if(row_count <= 0):
            return BaseResult.Success
        else:
            return BaseResult.Failure

    # 新增用户
    def Insert(self,entity:t_user)->BaseResult:
        self.session.add(entity)
        self.session.commit()
        return BaseResult.Success

    # 更新用户
    def Update(self,entity:t_user,userCode:str)->BaseResult:
        user = self.session.query(t_user).filter(t_user.UserCode == entity.UserCode).first()
        user.UserName = entity.UserName;
        user.Birthday = entity.Birthday;
        user.IdentityCard = entity.IdentityCard;
        user.Email = entity.Email;
        user.Mobile = entity.Mobile;
        user.Nick = entity.Nick;
        user.QQ = entity.QQ;
        user.Sex = entity.Sex;
        user.Signature = entity.Signature;
        user.Telephone = entity.Telephone;
        user.Title = entity.Title;
        user.ModifyTime = datetime.now();
        user.ModifyUserCode = userCode;
        self.session.commit()
        return BaseResult.Success


    # 判断用户是否有此权限
    def JudgeUserPermit(self,type:str, method:str, userCode:str)->BaseResult:
        sql = text(f"select COUNT(1) FROM t_permission  WHERE ResType='{type}' and ResMethod='{method}'  and PermitCode in (SELECT PermitCode FROM t_rolepermission WHERE RoleCode in (SELECT RoleCode FROM t_userrole WHERE UserCode='{userCode}'))");
        result = self.session.execute(sql)
        count = result.fetchone()[0]
        if(count > 0):
            return BaseResult.Success
        else:
            return BaseResult.Failure   

class BaseResult():
    def __init__(self,isSucessed:bool,message:str,mark=0,tag=None,total=0):
        self.IsSucessed=isSucessed
        self.Message=message
        self.Mark=mark
        self.Tag=tag
        self.Total=total



    IsSucessed:bool
    Message:str
    Mark:int
    Tag:any
    Total:int

    @staticmethod
    def Success():
        res=BaseResult(True,"Success")
        return res
    
    @staticmethod
    def Failure():
        res=BaseResult(True,"Failure")
        return res

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
m_pDbProcPic = new CDBProcess("sqlserver"); m_pDbProc->openDB("mysvr", "mydb", "myusername", "mypwd"); m_pDbProcPic = new CDBProcess("mysql"); m_pDbProc->openDB("localhost", "mydb", "root", "password"); m_pDbProcPic = new CDBProcess("access"); m_pDbProc->openDB("", strMDB, "sa", "password"); m_pDbProcPic = new CDBProcess("sqlite"); m_pDbProcPic->openDB("", "mysqlitedb"); CDBProcess使用说明 构造函数: CDBProcess(const QString strType); 参数:为数据库型,不区分大小写,支持的型有 sqlite mysql access sqlserver 例: CDBProcess db("sqlite"); -------------------------------------------------- 打开数据库 bool openDB(const QString strSvrName, //服务器名 const QString strDBname, //数据库名 const QString strUserID="", //用户名 const QString strUserPwd=""); //密码 打开数据库成功,返回true,否则返回false 对于sqlite,只有strDBname有效,其它参数忽略,如db.openDB("", "mysqlite.db") 对于MS Access数据库,strSvrName为空,用户名默认为"sa",如db.openDB("", "myaccess.mdb"); 对MSAccess数据库,也可通过一个UDL文件,打开,如db.openDB("my.udl", ""); mysql和sqlserver,就是各个参数依次提供,如db.openDB("svr1", "mydb", "user1", "abcd"); ----------------------------------------------------- 关闭数据库,CDBProcess析构时,亦会自动关闭数据库 void closeDB(); //db.closeDB(); ------------------------------------------------------ 执行Sql语句 bool excuteSQL(const QString); ------------------------------------------------------- 打开记录集 bool openRecordsetBySql(const QString strSql, //Sql语句 int idx = -1); //记录集id,用于标识记录集,默认值为-1 例: db.openRecordsetBySql("SELECT * FROM TB1", 5); 打开一个记录集,标识号为5,后面操作这个记录集,也要提供这个标识号 -------------------------------------------------------- 关闭记录集 void closeRecordset(int idx = -1); 例: db.closeRecordset(5); 关闭之前打开的标识为5的记录集 ----------------------------------- 数据库是否处在打开状态 bool isOpen() const; ------------------------------------ 记录集游标是否在结尾,参数为记录集标识 bool recEOF(int idx = -1) const; 例:bool b = db.RecBOF(5); ------------------------------------ 记录集游标是否在第一条记录之前,参数为记录集标识 bool recBOF(int idx = -1) const; ---------------------------------------- 删除一个表 bool dropTable(const QString); --------------------------------------------- 读取标识为idx记录集的当前记录的各字段值,方法如示例: bool getFieldsValueFromRec(int idx, const char* szFldInfo, ...) const; int iSN; QString strName; double dHeight; QDateTime dt; QByteArray ba; db.getFieldsValueFromRec(5, //记录集id "sn%d", &iSN, //字段名加型 sn为字段名%d表示整型,&iSN传入指针,保存返回字段值 "name%s", &strName, //字段名加型 name为字段名%s表示字符串(QString) "height&f", &dHeight, //字段名加型 height为字段名%f表示小数(double) "birthday%t", &dt, //字段名加型 birthday为字段名%t表示时间(QDateTime) "photo%b", &ba, //字段名加型 photo为字段名%b表示二进制流(QByteArray) CDBProcess::szEnd); //结束标志,"|" 执行后,各字段值就保存在iSN, strName等变量中了。 参数:第一个参数为记录集id 后面可变参数,字段%型标识,用于保存返回值的指针, 型标识:%d-int %s-QString %f-double %t-QDateTime %b-QByteArray --------------------------------------------------------------------------- 向一个数据表中填加一条记录 bool addFieldsValueToTbl(const QString strTbl, const char* szFldInfo, ...); 参数:第一个参数strTbl,为表名 后面是可变参数,为"字段%型标识",值(或指针),注int,double型直接传值,其它传指针 例: db.addFieldsValueToTbl("TB1", //表名 "sn%d", iSN, //字段名加型 sn为字段名%d表示整型,iSN传入值 "name%s", &strName, //字段名加型 name为字段名%s表示字符串(QString), 传入QString变量指针 "height&f", dHeight, //字段名加型 height为字段名%f表示小数(double),dHeight传入值 "birthday%t", &dt, //字段名加型 birthday为字段名%t表示时间(QDateTime),传入指针 "photo%b", &ba, //字段名加型 photo为字段名%b表示二进制流(QByteArray),传入指针 CDBProcess::szEnd); //结束标志,"|" ----------------------------------------------------------- 修改表中符合WHERE子句条件的记录 bool updateTblFieldsValue(const QString strTbl, QString strWhere, const char * szFldInfo, ... ); strTbl表名 strWhere SQL WHERE子句,如"WHERE sn=20" const char * szFldInfo, ...可变参数,同addFieldsValueToTbl 例: db.updateTblFieldsValue("TB1", "WHERE sn=20", "height&f", dHeight, "photo%b", &ba, CDBProcess::szEnd); ---------------------------------------------------------------- 以下几个函数分别是获取记录数,和记录光标移动。参数为记录集标识 long getRecordCount(int idx = -1) const; bool moveFirst(int idx = -1) const; bool movePrevious(int idx = -1) const; bool moveNext(int idx = -1) const; bool moveLast(int idx = -1) const; bool moveTo(int n, int idx = -1) const; -------------------------------------------------------------------- 返回数据库名 QString getDbName() const; ------------------------ 以下几个函数未验证 bool execStoreProcOfArgList(int idx, const QString strStoreProc, const char* szFldsInfo, ...); bool exexProc(const QString strStoreProc, QString str1, QString& str2); bool transaction(); bool commit(); bool rollback();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Rotion_深

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

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

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

打赏作者

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

抵扣说明:

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

余额充值