首先看下一个简单的例子

# 需求
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. Google advertiser 开发

    开发 相关知识: 单一归因与多重归因 当展示广告网络上发生一次展示时,您可按单一归因或多重归因记录对展示起到影响作用的条件. 单一归因 在使用单一归因时,系统只为指定的展示记录一个触发条件(如展示位置 ...

  2. Java String 函数常用操作 & format() 格式化输出,代码详解

    package _String_; import java.util.*; import java.math.*; import java.lang.*; public class _Strings ...

  3. IIS客户端没有权限

    运行CMDicacls c:\ /setintegritylevel M

  4. _event_worldstate

    EventId 事件ID ID WorldStateUI.dbc第10列数字部分 StartValue 起始值 Entry 更新世界状态需要击杀生物或摧毁物体的entry,正数为生物,负数为物体 St ...

  5. 切片对象的demo

    a = slice(, ) s = 'HelloWorld' print(a.indices(len(s))) for i in range(*a.indices(len(s))): print(s[ ...

  6. JavaSE习题 第八章 线程

    问答题 1.线程和进程是什么关系? 进程是程序的一次动态执行,对应了从代码加载,执行至执行完毕的一个完整的过程 线程是比进程更小的执行单位,一个进程在其执行过程中可以产生多个线程,形成多条执行线索 2 ...

  7. 【转】VC 利用DLL共享区间在进程间共享数据及进程间广播消息

    1.http://blog.csdn.net/morewindows/article/details/6702342 在进程间共享数据有很多种方法,剪贴板,映射文件等都可以实现,这里介绍用DLL的共享 ...

  8. 力扣(LeetCode)448. 找到所有数组中消失的数字

    给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次. 找到所有在 [1, n] 范围之间没有出现在数组中的数字. 您能在不使 ...

  9. ubuntu16.04 安装docker-ce,docker-compose

    2018.11.14更新 参考https://blog.csdn.net/qq_38199832/article/details/77803645 sudo curl -sSL https://dow ...

  10. 控制 datetimepicker 显示位置

    1. datetimepicker 位置  pickerPosition  有以下几个属性值,望文生义不解释 $('.form_datetime').datetimepicker({ pickerPo ...