zoukankan      html  css  js  c++  java
  • 我的第一个python web开发框架(27)——定制ORM(三)

      在上一章中,我们已经创建好ORM的基类了,接下来要做的就是将基类的常用方法一一实现。

      首先我们来看看之前项目中,最常见的获取指定主键的记录实体

    @get('/api/product/<id:int>/')
    def callback(id):
        """
        获取指定id的产品记录实体
        """
        sql = """select * from product where id = %s""" % (id,)
        # 读取记录
        result = db_helper.read(sql)
        if result:
            return web_helper.return_msg(0, '成功', result[0])
        else:
            return web_helper.return_msg(-1, "查询失败")

      从代码中可以看到,我们需要执行select * from product where id = xx从数据表中查询到我们想要的数据。

      要封装成ORM的方法,我需要需要注意下面几项事情:

      1.方法名必须是简单易懂的

      2.方法需要接收指定的主键值

      3.sql需要在方法中进行组装

      根据这些要求,我们可以很容易写出这个方法

        def get_model_for_pk(self, pk):
            """通过主键值获取数据库记录实体"""
            if not pk:
                return {}
            # 组装查询条件
            wheres = '%s = %s' % (self.__pk_name, str(pk))
            # 合成sql语句
            sql = "select %(column_name_list)s from %(table_name)s where %(wheres)s" % 
                  {'column_name_list': self.__column_name_list, 'table_name': self.__table_name, 'wheres': wheres}
            # 初化化数据库链接
            with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
                # 执行sql语句
                _result = db.execute(sql)
                # 对返回的内容进行处理
                if _result:
                    result = _result[0]
                else:
                    result = {}
            return result

      我们通过方法名(get_model_for_pk)应当可以知道,我们是通过主键来获取指定的记录实体内容。

      该方法需要传入的参数值是主键值pk

      在接收到主健值以后,我们需要对它进行简单的判断处理,如果它为空则直接返回空字典。

      在组合sql前,我们需要选对查询条件进行组装,这里我们直接使用self.__pk_name,在上一章初始化时定义好的默认项,在这里不直接使用id做为条件字段,是为了当出现主键名称为其他字符时,可以灵活处理。比如订单表使用code为主键时,就可以直接绑定code而不是自增id了。比如self.__pk_name初始值是id,主键pk值是1,那么组装后的查询条件为 id=1

      然后直接调用默认项查询字段名称self.__column_name_list和表名称self.__table_name来合成sql语句。例如self.__column_name_list初始值为*,self.__table_name初始值为product,那么合成的sql语句为:select * from product where id=1

      最后调用数据库操作类db_helper来执行sql语句(这里使用widh方法来初始化数据库操作类),将执行后的结果返回主程序

      针对上面这个读取产品记录实体的功能,我们像上一章一样,先创建好一个产品管理的逻辑类,继承ORM基类

    #!/usr/bin/env python
    # coding=utf-8
    
    from logic import _logic_base
    from config import db_config
    
    
    class ProductLogic(_logic_base.LogicBase):
        """产品管理表逻辑类"""
    
        def __init__(self):
            # 表名称
            __table_name = 'product'
            # 初始化
            _logic_base.LogicBase.__init__(self, db_config.DB, db_config.IS_OUTPUT_SQL, __table_name)

      我们就可以直接改造前面的接口调用代码了

    @get('/api/product/<id:int>/')
    def callback(id):
        """
        获取指定记录
        """
        # 实例化product表操作类ProductLogic
        _product_logic = product_logic.ProductLogic()
        # 执行get_model_for_pk()方法,获取记录实体
        model = _product_logic.get_model_for_pk(id)
        if model:
            return web_helper.return_msg(0, '查询成功', model)
        else:
            return web_helper.return_msg(-1, "查询失败")

      和前面的代码比较,代码看起来简单多了

      直接上单元测试看看执行效果

     1 #!/usr/bin/evn python
     2 # coding=utf-8
     3 
     4 import unittest
     5 from logic import product_logic
     6 
     7 class DbHelperTest(unittest.TestCase):
     8     """数据库操作包测试类"""
     9 
    10     def setUp(self):
    11         """初始化测试环境"""
    12         print('------ini------')
    13 
    14     def tearDown(self):
    15         """清理测试环境"""
    16         print('------clear------')
    17 
    18     def test(self):
    19         ##############################################
    20         # 只需要看这里,其他代码是测试用例的模板代码 #
    21         ##############################################
    22         # 实例化product表操作类ProductLogic
    23         _product_logic = product_logic.ProductLogic()
    24         # 执行get_model_for_pk()方法,获取记录实体
    25         model = _product_logic.get_model_for_pk(2)
    26         print(model)
    27 
    28         ##############################################
    29 
    30 if __name__ == '__main__':
    31     unittest.main()

      输出结果:

    ------ini------
    {'product_class_id': 1, 'place_of_origin': '广东广州', 'name': '饼干', 'id': 2, 'standard': '500g', 'is_enable': 1, 'add_time': datetime.datetime(2018, 7, 25, 23, 10, 4), 'quality_guarantee_period': '2018年12月', 'code': '20180212321211', 'content': '产品描述', 'front_cover_img': 'http://xxx.com/xxx.jpg'}
    ------clear------

      做到这一步,一个简单的通过主键值读取数据表记录实体的ORM方法就完成了。

      为了让这个读取记录实体的功能能应用的更加广泛,我们还需要对它进行改造与加工。

      在开始之前,大家再继续思考一下,我们获取记录实体,通过主键查询只是众多方法中的其中一个,我们还会经常使用各种条件的组合来进行查询,读取记录实体,所以这里我们可以实现自定义条件查询的方法

        def get_model(self, wheres):
            """通过条件获取一条记录"""
            # 如果有条件,则自动添加where
            if wheres:
                wheres = ' where ' + wheres
    
            # 合成sql语句
            sql = "select %(column_name_list)s from %(table_name)s %(wheres)s" % 
                  {'column_name_list': self.__column_name_list, 'table_name': self.__table_name, 'wheres': wheres}
            # 初化化数据库链接
            with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
                # 执行sql语句
                _result = db.execute(sql)
                # 对返回的内容进行处理
                if _result:
                    result = _result[0]
                else:
                    result = {}
            return result

      代码看起来与前面的get_model_for_pk()方法差不多,只不过将pk参数改为条件参数wheres,不需要再组合主键查询条件而已。由于两个函数部分代码一样,所以我们需要对get_model_for_pk()方法进行重构,直接将组装好的查询条件提交给get_model()方法来执行就可以了,将它返回的内容直接返回给主程序。

        def get_model_for_pk(self, pk, wheres=''):
            """通过主键值获取数据库记录实体"""
            if not pk:
                return {}
            # 组装查询条件
            wheres = '%s = %s' % (self.__pk_name, str(pk))
    
            return self.get_model(wheres)

      改造完成后,使用前面的单元测试跑一下,可以看到返回结果一样。增加了get_model()方法以后,我们就可以灵活的自定义任意的查询条件来读取记录了。这里要注意的是,使用get_model()方法查询时,有可能在查询时会返回多条记录,这个方法它只返回第一条记录。需要返回多条记录时,可以使用我们后续封装的其他ORM方法。

      

      本文对应的源码下载 (为了方便大家理解,源码包只放了这两章所用到的一些代码)

     

    版权声明:本文原创发表于 博客园,作者为 AllEmpty 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

    python开发QQ群:669058475(本群已满)、733466321(可以加2群)    作者博客:http://www.cnblogs.com/EmptyFS/

     

  • 相关阅读:
    查看yarn当前执行任务列表
    小白学开发(iOS)OC_ 字符串的获取 (2015-08-11)
    【leetcode】Search in Rotated Sorted Array (hard)
    【leetcode】Spiral Matrix II (middle)
    【leetcode】Spiral Matrix(middle)
    【leetcode】Reverse Bits(middle)
    【leetcode】Number of 1 Bits (easy)
    【leetcode】Set Matrix Zeroes(middle)
    【leetcode】Reorder List (middle)
    【leetcode】Reverse Linked List II (middle)
  • 原文地址:https://www.cnblogs.com/EmptyFS/p/9410998.html
Copyright © 2011-2022 走看看