需求说明
使用Python元类编程实现简单的Django Model定义、校验以及构造生成sql语句。
一、定义Field类
我们只定义了两个Field类:IntField、CharField,用于定义Model支持的数据类型以及对值的类型、长度、大小进行一些简单校验。
import numbers
class Field(object):
def __init__(self):
self._value = None
def __str__(self):
return self._value
def __get__(self, instance, owner):
return self._value
class IntField(Field):
def __init__(self, db_column=None, min_value=None, max_value=None, *args, **kwargs):
self.db_column = db_column
if min_value is not None and not isinstance(min_value, numbers.Integral):
raise ValueError('min_value must be int')
self.min_value = min_value
if max_value is not None and not isinstance(max_value, numbers.Integral):
raise ValueError('max_value must be int')
self.max_value = max_value
if min_value is not None and max_value is not None:
if min_value > max_value:
raise ValueError('min_value must smaller than max_value')
super().__init__()
def __set__(self, instance, value):
if not isinstance(value, numbers.Integral):
raise ValueError('IntField value must be int')
if self.min_value is not None and value self.max_value:
raise ValueError(f'IntField value must smaller than {self.max_value}')
self._value = value
class CharField(Field):
def __init__(self, db_column=None, max_length=None, *args, **kwargs):
self.db_column = db_column
if max_length is not None and not isinstance(max_length, numbers.Integral):
raise ValueError('max_length must be int')
elif max_length self.max_length:
raise ValueError(f'CharField value length must smaller than {self.max_length}')
self._value = value
二、定义元类
该元类主要用于将Model中定义的column以及db_table等初始化到Model的实例对象上。
class ModelMetaClass(type):
def __new__(cls, name, bases, attrs, **kwargs):
fields = {}
for key, value in attrs.items():
if isinstance(value, Field):
fields[key] = value
_meta = {}
attr_meta_class = attrs.get('Meta', None)
db_table = name.lower()
if attr_meta_class is not None:
db_table = getattr(attr_meta_class, 'db_table', db_table)
_meta['db_table'] = db_table
attrs['fields'] = fields
attrs['_meta'] = _meta
return super().__new__(cls, name, bases, attrs, **kwargs)
三、定义Model基类
Model基类主要用于支持Model创建对象的时候及初始化column值以及定义通用的orm处理逻辑函数。
class BaseModel(metaclass=ModelMetaClass):
def __init__(self, *args, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
super().__init__()
def save(self):
db_table = self._meta.get('db_table')
fields = []
values = []
for key, field in self.fields.items():
db_column = field.db_column
if db_column is None:
db_column = key.lower()
fields.append(db_column)
value = getattr(self, key)
values.append(str(value))
sql = f"insert {db_table}({','.join(fields)}) value({','.join(values)})"
print(sql)
四、定义Model实体类
class User(BaseModel):
name = CharField(max_length=10)
age = IntField(min_value=0, max_value=100)
class Meta:
db_table = 'user'
def __str__(self):
return self.name
五、测试
user = User(name='python', age=18)
user.save()
创建model类,以及调用save会输出经过orm转换后的sql语句:insert user(name,age) value(python,18)