参悟python元类(又称metaclass)系列实战(二)

参悟python元类(又称metaclass)系列实战(二)[Python基础]

写在前面

在上一章节参悟python元类(又称metaclass)系列实战(一)简单介绍了什么是元类、怎么用以及其作用。
本节内容主要为过渡,但同样重要。
有误的地方恳请大神指正下。

ORM

  • 全称“Object Relational Mapping”,即对象-关系映射,具体做法就是
    1. 把一张表映射成一个类
    2. 把表中的每一行数据,映射成一个类的实例
  • 目的是“写代码更简单,不用写SQL语句(但不可能完全取代sql)”

假设mysql(version: 5.5.62)中有如下一张表users

uid email passwd admin name birthday image created_at updated_at created_by updated_by is_deleted
101 admin@z417.top 21232f297a57a5a743894a0e4a801fc3 1 管理员 2020-11-03 about:blank 2020-11-03 08:31:32 2020-11-03 08:32:46 101 101 0
102 z417@z417.com 4a80b99f5591cdf5620014d5c7685fc6 0 z417 NULL about:blank 2020-11-03 09:46:29 2020-11-03 10:32:32 101 103 1
  • 具体的字段描述请阅读下面的建表语句
CREATE TABLE `users` (
  `uid` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(50) NOT NULL,
  `passwd` char(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT "",
  `admin` tinyint(1) unsigned NOT NULL DEFAULT "0" COMMENT "0普通用户,1管理员,2游客",
  `name` varchar(50) NOT NULL,
  `birthday` DATE COMMENT"用户生日",
  `image` varchar(500) NOT NULL DEFAULT "about:blank" COMMENT "头像,base64 encode in file",
  `created_at` timestamp NOT NULL DEFAULT "0000-00-00 00:00:00",
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `created_by` int(11) unsigned COMMENT "创建人uid",
  `updated_by` int(11) unsigned COMMENT "修改人uid",
  `is_deleted` tinyint(1) unsigned NOT NULL DEFAULT "0" COMMENT "1代表逻辑删除",
  PRIMARY KEY (`uid`),
  CONSTRAINT `fk_self_uidxCre` FOREIGN KEY(`created_by`) REFERENCES users(`uid`),
  CONSTRAINT `fk_self_uidxUpd` FOREIGN KEY(`updated_by`) REFERENCES users(`uid`),
  UNIQUE KEY `emailxDel` (`email`,`is_deleted`),
  UNIQUE KEY `namexDel` (`name`,`is_deleted`),
  KEY `index_created_at` (`created_at`)
) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

抽象出列的属性

  • 这里我们只关注字段类型、默认值、是否为主键,其余暂不care
  • 基于上一点,抽象出一个类如下
    class Field():
        """映射字段名、字段类型和默认值"""
        def __init__(self, columnType, primaryKey, default):
            self.columnType = columnType
            self.primaryKey = primaryKey
            self.default = default
    
        def __str__(self):
            """
            该方法在Field的实例被print时调用,这样自定义后,就不会打印内存地址了,
            而是打印‘<类名: columnType>’
            """
            # 这是python3.7及以后新增的写法,等于"<{}: {}>".format(self.__class__.__name__, self.columnType)
            return f"<{self.__class__.__name__}: {self.columnType}>"  
    
  • 对于users表可能需要再细分6种字段,分别如下
    class StrField(Field):
        """映射字符类型,如char和varchar"""
        def __init__(self, primaryKey=False, default=None, ddl="varchar(100)"):
            """
            主键、默认值和类型三要素,在实例化时候可传入参数定制,这里先给了默认值
            """
            super().__init__(ddl, primaryKey, default)
    
    class BooleanField(Field):
        """映射boolean类型"""
        def __init__(self, default=False):
            """
            mysql布尔类型关键字:boolean
            布尔类型不可能做主键,所以primaryKey写死False
            默认值False
            """
            super().__init__("boolean", False, default)
    
    class IntegerField(Field):
        """映射整型,如int"""
        def __init__(self, primaryKey=False, default=0, ddl="bigint"):
            """实例化时可通过参数定制3要素"""
            super().__init__(ddl, primaryKey, default)
    
    class FloatField(Field):
        """映射浮点类型,如float, real"""
        def __init__(self, primaryKey=False, default=0.0, ddl="real"):
            super().__init__(ddl, primaryKey, default)
    
    class TextField(Field):
        """映射大文本类型,如text"""
        def __init__(self, default=None, ddl="text"):
            """一般不会做主键,所以primaryKey写死False"""
            super().__init__(ddl, False, default)
    
    class DateTimeField(Field):
        """映射时间类型,如timestamp, date, datetime"""
        def __init__(self, default=None, ddl="timestamp"):
            """一般不会做主键,所以primaryKey写死False"""
            super().__init__(ddl, False, default)
    

有了上面的内容做铺垫,接下来就是把select,insert,update等sql操作整合到一个类里,下节再赘述

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 参悟python元类(又称metaclass)系列实战(二)