python之ORM

"""
    生成建表语句
    在创建类的时候
"""
import pymysql
import logging

host = "127.0.0.1"
port = 3306
user = "root"
password = "123321"
database = "youku"
auto_commit = True

# 是否输出调试信息
debug = False

 

 

 

class MyMeta(type):
    def __init__(self,cls_name,bases,namespace):
        table_name = cls_name # 把类名作为表名
        sql = "create table %s(" % table_name
        # 读取所有字段信息
        for k,v in namespace.items():
            # 包含了一些不是字段信息的值
            if isinstance(v,Field):
                text = ""
                text += v.name
                text = text + " " + v.column_type
                # 判断字段是否为主键
                if v.is_primary:
                    text = text + " primary key"
                if v.auto_increment:
                    text = text + " auto_increment"
                if v.default != None:
                    # 默认值是整型还是 字符串
                    if type(v.default) == int or type(v.default) == float:
                        text = text + " default " + str(v.default)
                        pass
                    elif type(v.default) == str:
                        text = text + (" default '%s'" % str(v.default))
                        pass
                    else:
                        raise TypeError("默认值必须为 字符或是数字")

                    # 把默认值拿出来判断是否mysql中的函数

                if v.constraint:
                    text = text + " " + v.constraint

                text += ","
                sql += text

        sql = sql.strip(",")
        sql += ");"
        # 创建一个连接器 执行sql创建表
        conn = Connector()
        try:
            count = conn.excute_sql(sql)
            if count:
                print("创建 %s 成功!" % table_name)
        except Exception as e:
            if debug:
                print("表已存在!!")
                print(type(e),e)

        super().__init__(cls_name,bases,namespace)
# 用于描述字段信息的类
class Field:
    def __init__(self,name,column_type,is_primary=False,auto_increment=False,default=None,constraint=None):
        """
        :param name:  字段名称
        :param column_type:  字段类型
        :param is_primary:  是否是主键
        :param auto_increment:  是否自增
        :param default:  默认值
        """
        self.name = name
        self.column_type = column_type
        self.is_primary = is_primary
        self.auto_increment = auto_increment
        self.default = default
        self.constraint =  constraint
class Connector:
    """
    用于连接数据库并执行sql语句
    """

    # 初始化  用于连接数据库
    def __init__(self):
        try:
            # 将连接对象作为属性  因为其他的函数中需要使用
            self.conn = pymysql.connect(host=host,
                                   port=port,user=user,
                                   password=password,
                                   database=database,
                                   autocommit=auto_commit)
            self.cursor = self.conn.cursor(pymysql.cursors.DictCursor) # 获取游标
            if debug:
                print("连接mysql成功!!!")
        except Exception as e:
            # 输出颜色为红色
            logging.error("连接数据库失败!")
            logging.error(type(e))
            logging.error(e)


    # 用于执行  删除 添加 修改  返回值是受影响的行数
    def excute_sql(self,sql,args=None,is_select = False):
        count = self.cursor.execute(sql,args) # count 表示受影响的行数  delete insert  update
        #self.conn.commit()
        if is_select:
            return self.cursor.fetchall()
        return count
class BaseModel:
    # 创建工具时 直接创建连接器 避免重复创建
    conn = Connector()
    """
    封装一个生成insert 语句的功能
    插入语句需要接受一个对象作为 参数 然后将对象中包含的数据 拿出来拼接成sql语句
    """
    def save(self):
        # print(obj.__dict__)
        #表名来自于类名
        # %s的个数 由对象的属性决定 id数据不需要从obj获取    总的属性个数-1
        ks = []
        vs = []
        for k,v in self.__dict__.items():
            ks.append(k)
            vs.append("%s")
        ks =  ",".join(ks)
        vs = ",".join(vs)

        sql = "insert into %s(%s) values (%s);" % (self.__class__.__name__,ks,vs)
        count = self.conn.excute_sql(sql,list(self.__dict__.values()))
        if count:
            return True

    def delete(self):
        """
        表名,条件 和 值
        :param obj: 要删除的对象
        :return:
        """
        t_name = self.__class__.__name__
        sql = "delete from "+t_name+" where id  = %s;"

        count = self.conn.excute_sql(sql,self.id)
        if count:
            print("删除成功!")
    def update(self):
        """
        :param new_obj:  包含了所有数据
        :return:
        """
        # u = User("张三","123")
        t_name = self.__class__.__name__
        ks = []
        vs = []
        for k,v in self.__dict__.items():
            if k == "id":continue
            t = "%s = %%s" % k
            ks.append(t)
            vs.append(v)

        kstext = ",".join(ks)
        sql = "update "+t_name+" set "+kstext+" where id = %s" % self.id
        # print(kstext)
        # print(vs)
        # print(sql)
        count = self.conn.excute_sql(sql,vs)
        if count:
            print("更新成功!")

    @classmethod
    def get(cls,condition=None,args=None,order_column=None,asc=True,limit=None):
        """
        :param cls:  要查询的类
        :param condition:  要查询的条件
        :param args: 查询的参数
        :param order_column:  排序的列
        :param asc:  默认为升序
        :param limit: 要获取的条数  (0,10)  (10,)
        :return:
        """
        t_name = cls.__name__
        sql = "select *from %s" % t_name
        if condition: #如果有条件
            sql += " where %s" % condition
        if order_column:#如果需要排序
            sql += " order by %s" % order_column
            if not asc: # 如果是降序
                sql += " desc"
        if limit:#如果需要分页
            if len(limit) == 1:# 仅有条数
                sql += " limit %s,%s" % (0, limit[0])
            elif len(limit) == 2: # 既有开始为止又有条数
                sql += " limit %s,%s" % (limit[0], limit[1])
            else:
                raise TypeError("limit 仅能接收1-2个值")

        print(sql)
        # 字典转对象
        objs = []
        data = cls.conn.excute_sql(sql,args,is_select=True) # 查询结果为一个列表 里面一堆字典
        for dic in data: #遍历字典 把每一个字典都转为以个对象 存储到列表中并返回
            obj = object.__new__(cls) # 创建空对象
            obj.__dict__.update(dic) #设置一系列属性
            objs.append(obj) # 加到列表中

        return objs # 返回列表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值