首先看下一个简单的例子

# 需求
import numbers class Field:
pass class IntField(Field):
# 数据描述符
def __init__(self, db_column, min_value=None, max_value=None):
self._value = None
self.min_value = min_value
self.max_value = max_value
self.db_column = db_column
if min_value is not None:
if not isinstance(min_value, numbers.Integral):
raise ValueError("min_value must be int")
elif min_value < 0:
raise ValueError("min_value must be positive int")
if max_value is not None:
if not isinstance(max_value, numbers.Integral):
raise ValueError("max_value must be int")
elif max_value < 0:
raise ValueError("max_value must be positive int")
if min_value is not None and max_value is not None:
if min_value > max_value:
raise ValueError("min_value must be smaller than max_value") def __get__(self, instance, owner):
return self._value def __set__(self, instance, value):
if not isinstance(value, numbers.Integral):
raise ValueError("int value need")
if value < self.min_value or value > self.max_value:
raise ValueError("value must between min_value and max_value")
self._value = value class CharField(Field):
def __init__(self, db_column, max_length=None):
self._value = None
self.db_column = db_column
if max_length is None:
raise ValueError("you must spcify max_lenth for charfiled")
self.max_length = max_length def __get__(self, instance, owner):
return self._value def __set__(self, instance, value):
if not isinstance(value, str):
raise ValueError("string value need")
if len(value) > self.max_length:
raise ValueError("value len excess len of max_length")
self._value = value

上述为属性描述符

元类的应用

class ModelMetaClass(type):
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs) class BaseModel(metaclass=ModelMetaClass):
def __init__(self,*args,**kwargs):
for key,value in kwargs.items():
setattr(self,key,value)
# return super().__init__() class User(BaseModel):
name = CharField(db_column="name", max_length=10)
age = IntField(db_column="age", min_value=1, max_value=100) class Meta:
db_table = 'user' if __name__ == "__main__":
user = User(name="bobby", age=28)
# user.name = "bobby"
# user.age = 28
# user.save()
print(user.name)
print(user.age)
print(user.Meta)

执行后结果:

bobby
28
<class '__main__.User.Meta'>

进一步改进代码:

class ModelMetaClass(type):
"""
name 类名
bases 基类(元组)
attrs:属性
还记得下面type生成类的使用方法吗?
User = type("User", (BaseClass, ), {"name":"user", "say":say})
"""
def __new__(cls, name, bases, attrs, **kwargs):
if name == "BaseModel":
return super().__new__(cls, name, bases, attrs, **kwargs)
fields = {}
for key,value in attrs.items():
if isinstance(value,Field):
fields[key] = value
attrs_meta = attrs.get('Meta',None)
_meta = {}
db_table = name.lower()
if attrs_meta is not None:
table = getattr(attrs_meta,'db_table',None)
if table is not None:
db_table = table
_meta['db_table'] = db_table
attrs['_meta'] = _meta
attrs['fields'] = fields
del attrs["Meta"]
return super().__new__(cls, name, bases, attrs, **kwargs) class BaseModel(metaclass=ModelMetaClass):
def __init__(self,*args,**kwargs):
for key,value in kwargs.items():
setattr(self,key,value)
# return super().__init__() class User(BaseModel):
name = CharField(db_column="name", max_length=10)
age = IntField(db_column="age", min_value=1, max_value=100) class Meta:
db_table = 'user' if __name__ == "__main__":
user = User(name="bobby", age=28)
# user.name = "bobby"
# user.age = 28
# user.save()
print(user.name)
print(user.age)
print(user._meta)
print(user.fields)

执行结果:

bobby
28
{'db_table': 'user'}
{'age': <__main__.IntField object at 0x0000000000C1F438>, 'name': <__main__.CharField object at 0x0000000000C1F3C8>}

元类应用ORM实现的更多相关文章

  1. Python 元类实现ORM

    ORM概念 ORM(Object Ralational Mapping,对象关系映射)用来把对象模型表示的对象映射到基于 SQL  的关系模型数据库结构中去.这样,我们在具体的操作实体对象的时候,就不 ...

  2. 元类实现ORM

    1. ORM是什么 ORM 是 python编程语言后端web框架 Django的核心思想,"Object Relational Mapping",即对象-关系映射,简称ORM. ...

  3. 使用元类 编写ORM

    元类 一句话: 元类定制类的创建行为 知识点 1.类的创建: python这种动态语言,函数和类的定义,不是编译时定义的,而是运行时动态创建的. Python解释器遇到class定义时,仅仅是扫描一下 ...

  4. 04 -- 元类和ORM

    本篇主要介绍元类,为什么说一切皆对象:如何动态的创建类等:以及ORM,即什么是ORM等知识 一.元类 1.1 在Python中一切皆对象 在学习元类中我们首先需要了解一个概念-- python中一切皆 ...

  5. 元类、orm

    目录 一.内置函数exec 二.元类 1. 什么是元类 2. 元类的作用 3. 创建类的两种方法 4. 怎么自定义创建元类 三.ORM 1. ORM中可能会遇到的问题 2. ORM中元类需要解决的问题 ...

  6. python-元类和使用元类实现简单的ORM

    元类 面向对象中,对象是类的实例,即对象是通过类创建出来的,在python中,一切皆对象,同样,类也是一个对象,叫做类对象,只是这个类对象拥有创建其子对象(实例对象)的能力.既然类是对象,那么类是通过 ...

  7. Python面向对象篇之元类,附Django Model核心原理

    关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了. Python面向对象之类的方法和属性 本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django. 在Python中有一 ...

  8. 神级程序员通过两句话带你完全掌握Python最难知识点——元类!

    千万不要被所谓"元类是99%的python程序员不会用到的特性"这类的说辞吓住.因为 每个中国人,都是天生的元类使用者 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生 ...

  9. Python中的元类

    从前面"Python对象"文章中了解到,在Python中一切都是对象,类可以创建实例对象,但是类本身也是对象. class C(object): pass c = C() prin ...

随机推荐

  1. vs添加webservice

    VS2010中添加WebService注意的几个地方 添加web引用和添加服务引用有什么区别? 2.4.1 基础知识——添加服务引用与Web引用的区别 C#之VS2010开发Web Service V ...

  2. nsswitch & pam

    nsswitch & pam nsswitch是名称解析框架服务,pam是认证框架服务 对主机来说,有两个功能可能用到框架性服务 1.名称解析: name: id 2.认证服务:验证当前请求获 ...

  3. Go 结构体(Struct)

    引用曾经看到的一篇文章里面对 Golang 中结构体的描述,如果说 Golang 的基础类型是原子,那么 结构体就是分子.我们都知道分子是由原子组成的,换言之就是结构体里面可以包含基础类型.切片. 字 ...

  4. vue中click阻止事件冒泡,防止触发另一个事件

    在使用el-upload组件时,在其中放置了一个删除按钮的图片. 当点击图片,本想只删除上传的视频,但是意外触发了el-upload中的事件 解决办法:用stop,结果只删除当前预览,不触发上传事件. ...

  5. SMTP发送邮件

    SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件.HTML邮件以及带附件的邮件. Python对SMTP支持有smtplib和email两个模块,email负责构造邮件, ...

  6. 【Selenium2】【Jenkins】

    1. 下载Tomcat ,Windows7 环境,http://tomcat.apache.org/  我下载的是版本8 2. 下载Jenkins,Windows7 环境,http://jenkins ...

  7. 数据库备份出现警告:Warning: Using a password on the command line interface can be insecure. Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even thos

    1.先来看原备份数据库语句: mysqldump -h 127.0.0.1 -uroot -ppassword database > /usr/microStorage/dbbackup/cap ...

  8. Could not find com.android.tools.build:aapt2:3.2.1-4818971.

    Could not find com.android.tools.build:aapt2:-. Searched in the following locations: file:/H:/Androi ...

  9. Vscode中运行js文件或部分代码 ,在下面cmd输出中显示结果

    重启 vscode,  这个插件  真好用,, 赞个 ....

  10. 修改linux镜像

    修改镜像的常用命令有: guestfish,guestmount等. ●修改静态文件. 命令:guestfish 安装包:yum install -y guestfish ①mount镜像:guest ...