Model
的初始化方法主要继承自BaseModel
类的__new__方法。 下面粗略的通过源码来看看:
class BaseModel(type):
# 定义可被继承的属性列表(全局)
inheritable = set([
'constraints', 'database', 'db_table_func', 'indexes', 'order_by',
'primary_key', 'schema', 'validate_backrefs', 'only_save_dirty'])
def __new__(cls, name, bases, attrs):
# 如果没有父类,则之间创建BaseModel类
if not bases:
return super(BaseModel, cls).__new__(cls, name, bases, attrs)
# Meta类的属性通过meta_options存储在Model类中
meta_options = {}
# 将Meta从属性中移除,将Meta中的非私有属性加入meta_options中
meta = attrs.pop('Meta', None)
if meta:
for k, v in meta.__dict__.items():
if not k.startswith('_'):
meta_options[k] = v
# 从meta中获取主键信息
model_pk = getattr(meta, 'primary_key', None)
parent_pk = None
############################################################
# 开始考虑从父类中继承的情况
#############################################################
for b in bases:
if not hasattr(b, '_meta'):
continue
base_meta = getattr(b, '_meta')
if parent_pk is None:
parent_pk = deepcopy(base_meta.primary_key)
all_inheritable = cls.inheritable | base_meta._additional_keys
# 获取父类中的Meta内部类字段,只考虑all_inheritable中的字段
for (k, v) in base_meta.__dict__.items():
if k in all_inheritable and k not in meta_options:
meta_options[k] = v
# 获取父类中的Fields, 即表的字段
for (k, v) in b.__dict__.items():
if k in attrs:
continue
if isinstance(v, FieldDescriptor):
if not v.field.primary_key:
attrs[k] = deepcopy(v.field)
# initialize the new class and set the magic attributes
cls = super(BaseModel, cls).__new__(cls, name, bases, attrs)
ModelOptionsBase = meta_options.get('model_options_base', ModelOptions)
cls._meta = ModelOptionsBase(cls, **meta_options)
cls._data = None
cls._meta.indexes = list(cls._meta.indexes)
# 默认表名的设定,Model名的小写,然后将非数字和英文字符换成'_'
if not cls._meta.db_table:
cls._meta.db_table = re.sub('[^\w]+', '_', cls.__name__.lower())
# replace fields with field descriptors, calling the add_to_class hook
# 这里筛选attr中的Field类型字段,设置Model中的数据类型
# 也许可以测试一下类里面的函数是怎么继承的
fields = []
for name, attr in cls.__dict__.items():
if isinstance(attr, Field):
if attr.primary_key and model_pk:
raise ValueError('primary key is overdetermined.')
elif attr.primary_key:
model_pk, pk_name = attr, name
else:
fields.append((attr, name))
composite_key = False
# 默认主键的设置,如果无法从父类继承,,则使用'id'为key, 也就是行号
if model_pk is None:
if parent_pk:
model_pk, pk_name = parent_pk, parent_pk.name
else:
model_pk, pk_name = PrimaryKeyField(primary_key=True), 'id'
elif isinstance(model_pk, CompositeKey):
pk_name = '_composite_key'
composite_key = True
# 如果model本身有主键的情况
if model_pk is not False:
model_pk.add_to_class(cls, pk_name)
cls._meta.primary_key = model_pk
cls._meta.auto_increment = (
isinstance(model_pk, PrimaryKeyField) or
bool(model_pk.sequence))
cls._meta.composite_key = composite_key
# 设置Fields
for field, name in fields:
field.add_to_class(cls, name)
# create a repr and error class before finalizing
# __unicode__的设置
if hasattr(cls, '__unicode__'):
setattr(cls, '__repr__', lambda self: '<%s: %r>' % (
cls.__name__, self.__unicode__()))
# 错误信息
exc_name = '%sDoesNotExist' % cls.__name__
exc_attrs = {'__module__': cls.__module__}
exception_class = type(exc_name, (DoesNotExist,), exc_attrs)
cls.DoesNotExist = exception_class
cls._meta.prepared()
if hasattr(cls, 'validate_model'):
cls.validate_model()
return cls
人的一生只有两万来天,效率至上