python对于mysql数据库操作类的相关方法及感悟

概述

本着磨刀不误砍柴工、高内聚低耦合的代码原则,带着心中向往的行云流水的敲代码向往,秉承绝不走回头路、我的代码我最屌的原则记录了此文。

对于数据库数据的操作,力要写一个万能、通用且高效率的数据库操作类。
话不多说,直接上代码:

import pymysql


class MysqlHelper:
    def __init__(self):
        self._user = db_user
        self._password = db_pwd
        self._charset = 'utf8'
        self._port = port
        self._host = db_host
        self._db_name = db_name
        self._conn = self.connect_mysql()
        if self._conn:
            self._cursor = self._conn.cursor()

    def connect_mysql(self):
        """
        连接数据库
        :return:
        """
        conn = pymysql.connect(host=self._host,
                               user=self._user,
                               passwd=self._password,
                               db=self._db_name,
                               port=self._port,
                               cursorclass=pymysql.cursors.DictCursor,
                               charset=self._charset,
                               )
        return conn

    def close(self):
        """
        关闭数据库连接
        :return:
        """
        self._cursor.close()
        self._conn.close()

    def execute(self, *args, params=None):
        """
        执行多条sql
        :param params:
        :param args:
        :return:
        """
        if params is None:
            params = []
        effect = 0
        for sql in args:
            num = self._cursor.execute(sql, params)
            effect += num
        self._conn.commit()
        self.close()
        return effect

    def select_multi(self, *args, params=None):
        """
        查询语句,可以执行多条查询
        :param args:
        :param params:
        :return: 返回元祖res:结果,num查询出行数
        """
        if params is None:
            params = []
        i = 1
        res = {}
        for sql in args:
            num = self._cursor.execute(sql, params)
            sql_results = self._cursor.fetchall()
            res['result%s' % i] = sql_results
            res['effect%s' % i] = num
            i += 1
        self.close()
        return res

    def select(self, sql, act='all', params=None):
        """
        查询语句方法
        :param act:
        :param sql:
        :param params:
        :return: 返回字典res:结果,num查询出行数
        """
        global res
        if params:
            pass
        else:
            params = []
        if act == 'all':
            num = self._cursor.execute(sql)
            sql_results = self._cursor.fetchall()
            res = {
                'result': sql_results,
                'effect': num
            }
        self.close()
        return res

好了,以上代码就是一个基本上可以直接使用的数据库操作类了,简述来说呢就是select_multi方法用来执行多条查询sql语句,select方法来执行单条语句(区别不大,但是各有用处),execute方法来执行多条操作语句。

之所以写了一个select_multi方法和execute通用多条语句就是用来仿写数据库中的事务操作,减少了每条语句对于数据库的连接、访问、关闭的这一系列操作,提高了效率。
但是对于cursor().execute()方法又是比较特殊的。

一、问题所在

先粘一段源代码:

def execute(self, query, args=None):
        """Execute a query

        :param str query: Query to execute.

        :param args: parameters used with query. (optional)
        :type args: tuple, list or dict

        :return: Number of affected rows
        :rtype: int

        If args is a list or tuple, %s can be used as a placeholder in the query.
        If args is a dict, %(name)s can be used as a placeholder in the query.
        """
        while self.nextset():
            pass

        query = self.mogrify(query, args)

        result = self._query(query)
        self._executed = query
        return result

可以看出来execute方法里面有两个参数而对于args是非必传,查看过文档,在调用时的param参数在使用时是用来避免sql注入而存在的,这样就能避免了恶意攻击数据库等行为。但是了解过这点之后,在某些sql语句中例如

DATE_FORMAT(CURRENT_DATE,'%Y-%m-%d')

日期函数中的%Y却又会报错,网上很多方法都是将单%变成双%避免被认定为占位符而存在。

报错截图.jpg

二、水落石出

对于Python中的三引号,将单%变为双%在更新之后又不好用了,会直接认定为是字符串%%,好坑......
于是再次观察源代码在execute()中的mogrify()方法

    def mogrify(self, query, args=None):
        """
        Returns the exact string that is sent to the database by calling the
        execute() method.

        This method follows the extension to the DB API 2.0 followed by Psycopg.
        """
        conn = self._get_db()
        if PY2:  # Use bytes on Python 2 always
            query = self._ensure_bytes(query, encoding=conn.encoding)

        if args is not None:
            query = query % self._escape_args(args, conn)

        return query

传入了上层函数传来的args参数、而在函数中对于args进行了一次判定,而对于避免sql注入而传入的param参数,尽管为空,但是是一个空列表而非None对象,所以会卡在self._escape_args(args, conn)方法上,结果清晰明了了。
那么,改进!

    def select(self, sql, act='all'):
        """
        查询语句方法
        :param act:
        :param sql:
        :param params:
        :return: 返回字典res:结果,num查询出行数
        """
        global res
        if act == 'all':
            num = self._cursor.execute(sql)
            sql_results = self._cursor.fetchall()
            res = {
                'result': sql_results,
                'effect': num
            }
        self.close()
        return res

这样就通用的多了,舒服。当然,也可以自己加很多种操作方法,那就取决于你啦。玩的开心。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 223,689评论 6 521
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,685评论 3 401
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 170,676评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,496评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,512评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,044评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,423评论 3 427
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,399评论 0 278
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,923评论 1 323
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,973评论 3 343
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,117评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,761评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,440评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,929评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,045评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,609评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,147评论 2 363

推荐阅读更多精彩内容