(拜託 我這纔是真的原理好麼。。。網上看了一堆 都是使用方式?也可能我沒找到真的原理。。。)
part1 加載過程
1、test/model.py
from django.db import models
class A(models.Model):
name = models.CharField()
class Meta:
db_table = "approve"
2、test/views.py
A.objects.filter(name='haha')
繼承的models.Model
取的是
django/db/models/base.py
裏class Model(six.with_metaclass(ModelBase)):
class Model
是元類ModelBase
的類對象,實現save() delete()
ModelBase
主要有三個方法,newclass時候調用add_to_class增加一堆_meta屬性、_prepare方法綁定manager
,然後返回class
copy_managers(cls, base_managers)
:給cls添加base_managers裏的manager屬性add_to_class(cls, name, value)
:實現setattr(cls, name, value)
_prepare(cls)
:發信號、讀取options.py的_prepare方法,基礎上重寫,然後再實現ensure_default_manager(cls)
ensure_default_manager
這個方法在manager.py中,主要目的實現下面兩行。
# Ensures that a Model subclass contains a default manager and sets the
_default_manager attribute on the class. Also sets up the _base_manager
points to a plain Manager instance (which could be the same as
_default_manager if it's not a subclass of Manager).
cls.add_to_class('objects', Manager())
cls._base_manager = cls.objects
然後Manager()是啥呢?帶有QuerySet信息的BaseManager對象
from django.db.models.query import QuerySet
class Manager(BaseManager.from_queryset(QuerySet)):
pass
# BaseManager.from_queryset,創建class,並把queryset_class方法列表加到類裏面
@classmethod
def from_queryset(cls, queryset_class, class_name=None):
……
#BaseManager._get_queryset_methods,返回queryset_class方法列表
for循環:
class_dict.update(cls._get_queryset_methods(queryset_class))
return type(class_name, (cls,), class_dict)
————————————
所以,寫了class A(models.Model)以後,orm會自動爲類創建object方法,值爲Manager()對象,然後Manager()對象返回的是一個類,這個類具有一堆queryset方法,並且orm爲當前類初始化一些_meta信息
————————————
part2 queryset工作方式
django/db/models/query.py
,class QuerySet(object)
上面from_queryset
方法內用for循環了queryset_class
所以調用時候就會循環class QuerySet(object)
的def __iter__(self)
方法
順序如下:
def __iter__(self)
——>def _fetch_all(self)
——>def iterator(self)
def iterator(self):
"""
An iterator over the results from applying this QuerySet to the
database.
"""
db = self.db
# 獲取sql編譯器,準備編譯sql語句
compiler = self.query.get_compiler(using=db)
# 獲取結果
results = compiler.execute_sql()
……
for row in compiler.results_iter(results):
obj = model_cls.from_db(db, init_list, row[model_fields_start:model_fields_end])
……
yield obj