它是由metaclass添加的,但以一种有点加密的方式.事实上,在ModelBase
的_preprare
级中,它不是Model
的超级级,而是typeclass,contributes this to the class [src]:
def _prepare(cls):
# …
if not opts.managers:
# …
cls.add_to_class("objects", manager)
# …
.add_to_class
方法将调用管理器上的.add_to_class
,然后将其自身设置为类对象上的属性.
然而,每款车型都有.objects
分的说法是不正确的.只有在您没有自己指定经理的情况下才会出现这种情况.事实上,如果你定义一个模型:
class MyModel(models.Model):
mymanager = models.Manager()
则MyManager
将not包含.objects
.
至于.all()
方法本身,它与_get_queryset_methods
一起工作.它们返回一个字典,其中包含方法及其方法的名称.因此,这将返回一个将'all'
映射到返回self.get_queryset().all()
的方法的字典,因为get_queryset
将返回QuerySet
,it will thus call .all()
on that queryset [src]:
@classmethod
def _get_queryset_methods(cls, queryset_class):
def create_method(name, method):
@wraps(method)
def manager_method(self, *args, **kwargs):
return getattr(self.get_queryset(), name)(*args, **kwargs)
return manager_method
new_methods = {}
for name, method in inspect.getmembers(
queryset_class, predicate=inspect.isfunction
):
# Only copy missing methods.
if hasattr(cls, name):
continue
# Only copy public methods or methods with the attribute
# queryset_only=False.
queryset_only = getattr(method, "queryset_only", None)
if queryset_only or (queryset_only is None and name.startswith("_")):
continue
# Copy the method onto the manager.
new_methods[name] = create_method(name, method)
return new_methods
大多数IDE、代码分析工具等确实无法推导出模型具有.objects
属性,因为它源自类型类中的一些复杂代码.
然而,PyCharm专业版有一个Django插件,可以更好地"理解"Django,因为开发人员已经硬编码了这样的逻辑.因此,它包含了一些不分析类型类代码的逻辑,而只是知道,因为模块的开发人员说了这一点,经理补充道.
Python是一种非常灵活的、动态类型的语言,这通常是一个好主意.但代码分析有时不能遵循元类等的复杂性,因此最终无法看到如何将项添加到类中,这是一个缺点,例如,与静态类型语言相比.