`.objects`属性被添加到django的models中的示例命名空间,

uqcuzwp8  于 2023-04-22  发布在  Go
关注(0)|答案(1)|浏览(108)

当我们在www.example.com中views.py编写类似any_model_name.objects.all()的代码时,它会给我们带来所有从any_model_name类模型中初始化的对象。(任何模型都应该继承的那个),我就是找不到.objects属性出现的地方,没有类似的东西,也没有.all()方法属性。我的pycharm也有同样的观点,它用红色下划线标出了.objects,并说“Unresolved attribute reference 'objects' for class 'any_model_name'”。是什么魔法阻止了我在django代码中找到第一次出现.objects的地方?

yzuktlbb

yzuktlbb1#

它是由 metaclass 添加的,但有点神秘。实际上,在ModelBase_preprare类中,它不是Model的超类,而是它的 typeclass,将此贡献给类[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将 * 不 * 包含.objects
至于.all()方法本身,它与_get_queryset_methods一起工作。这些返回一个包含方法名称及其方法的字典。因此,这将返回一个字典,该字典将'all'Map到返回self.get_queryset().all()的方法,因为get_queryset将返回QuerySet,因此它将在该queryset [src]上调用.all()

@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 professional有一个Django插件,可以更好地“理解”Django,因为开发人员已经硬编码了这样的逻辑。因此,它包含一些逻辑,不分析类型类代码,但只是知道,因为模块的开发人员说,添加了管理器。
Python是非常灵活的动态类型语言,这通常是一个好主意。但是代码分析有时不能跟踪元类的复杂性,因此最终无法看到如何将项添加到类中,这是一个缺点,例如,与静态类型语言相比。

相关问题