首先看下一个简单的例子

# 需求
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. postgresql:array & foreach

    --数组: SELECT (ARRAY['{101, 111, 121}', '{201, 211, 221}'])[1]::text[]; SELECT (ARRAY['{101, 111, 121 ...

  2. mysql中if()函数使用

    博主原创,转载请注明出处: 在mysql中if()函数的用法类似于java中的三目表达式,其用处也比较多,具体语法如下: IF(expr1,expr2,expr3),如果expr1的值为true,则返 ...

  3. 【译】第42节---EF6-DbSet.AddRange & DbSet.RemoveRange

    原文:http://www.entityframeworktutorial.net/entityframework6/addrange-removerange.aspx EF 6中的DbSet引入了新 ...

  4. python学习 day014打卡 内置函数二&递归函数

    本节主要内容: 1.lambda匿名函数 2.sorted() 3.filter() 4.map() 5.递归函数 6.二分法 一.lambda匿名函数 为了解决一些简单的需求而设计的一句话函数 # ...

  5. webpack插件配置(二)- HtmlWebpackPlugin

    作用 简化Html文件的创建,以便为你的webpack bundle包提供服务.这对于在文件名中包含每次会随着编译而发生变化的hash的webpack bundle尤其有用.插件可以生成一个HTML文 ...

  6. linux例行性任务(定时作业)

    linux定时作业(例行性任务) linux有两种定时作业方式: • at : 这个工作仅执行一次就从 Linux 系统中的排程中取消: • cron : 这个工作将持续例行性的作下去! at仅执行一 ...

  7. R语言 让纵坐标的标签显示为横向

    参考自153分钟学习R语言 坐标y 上的数字如何水平放置?仍然是绘图参数问题: ?par # see  lasplot(0, 0, xaxt="n" , type="n& ...

  8. 力扣(LeetCode)520. 检测大写字母

    给定一个单词,你需要判断单词的大写使用是否正确. 我们定义,在以下情况时,单词的大写用法是正确的: 全部字母都是大写,比如"USA". 单词中所有字母都不是大写,比如"l ...

  9. CSS 控制鼠标在元素停留的样式

    以下资料来自网络,收藏学习总结用: 有时候需要改变鼠标样式,DIV 可以改成手型等,A也可以改成光标形式 巧合要用到鼠标样式效果,就顺便整理了下十五种CSS鼠标样式,小例子供大家使用啊.CSS鼠标样式 ...

  10. 牛客OI周赛4-提高组 B 最后的晚餐(dinner)

    最后的晚餐(dinner) 思路: 容斥 求 ∑(-1)^i * C(n, i) * 2^i * (2n-i-1)! 这道题卡常数 #pragma GCC optimize(2) #pragma GC ...