美文网首页
ORM-model类.objects分析

ORM-model类.objects分析

作者: 小吉头 | 来源:发表于2020-06-23 16:17 被阅读0次

数据库表如下

#models.py
class Author(models.Model):
    """作者模型"""
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    email = models.EmailField()

    class Meta:
        db_table = "author"
#views.py
from .models import Author

def queryset(request):
    authors = Author.objects.all()
    print(authors)
    return HttpResponse("success")

Author类的objects属性

def queryset(request):
    # authors = Author.objects.all()
    # print(authors)
    print(type(Author.objects))
    return HttpResponse("success")
>>><class 'django.db.models.manager.Manager'>

Author.objects是django.db.models.manager.Manager类的实例,导入Manager类查看源码:

django.db.models.manager.Manager

class Manager(BaseManager.from_queryset(QuerySet)):
    pass

Manager类继承自BaseManager.from_queryset(QuerySet),调用BaseManger的类方法from_queryset,参数是QuerySet

QuerySet类里有什么

可以查看类结构,有all方法,filter方法,order_by方法,aggregate方法,annotate方法等...,发现都是操作ORM时用到的方法

BaseManager.from_queryset(QuerySet)源码查看

    @classmethod
    def from_queryset(cls, queryset_class, class_name=None):
        if class_name is None:
            class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
        class_dict = {'_queryset_class': queryset_class,} # class_dict = {'_queryset_class': QuerySet,}
        class_dict.update(cls._get_queryset_methods(queryset_class))
        return type(class_name, (cls,), class_dict)

前两句代码翻译如下:

class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__) # class_name = "BaseManagerFromQuerySet"

class_dict = {'_queryset_class': queryset_class,} # class_dict = {'_queryset_class': QuerySet,}

class_dict.update(cls._get_queryset_methods(queryset_class))

查看BaseManger._get_queryset_methods(QuerySet)类方法源码:

@classmethod
    def _get_queryset_methods(cls, queryset_class):
        def create_method(name, method):
            def manager_method(self, *args, **kwargs):
                return getattr(self.get_queryset(), name)(*args, **kwargs)
            manager_method.__name__ = method.__name__
            manager_method.__doc__ = method.__doc__
            return manager_method

        new_methods = {}
        # Refs http://bugs.python.org/issue1785.
        predicate = inspect.isfunction if six.PY3 else inspect.ismethod
        for name, method in inspect.getmembers(queryset_class, predicate=predicate):
            # 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

将QuerySet类中的指定方法拷贝到new_methods字典,返回new_methods。
更新class_dict,参数是new_methods这个字典,class_dict中没有的键会新增,如果键存在,覆盖键对应的值。

type(class_name, (cls,), class_dict)作用是动态创建类

type(BaseManagerFromQuerySet, (BaseManager,), class_dict)
第一个参数:指定创建的类的名字,创建的类名是BaseManagerFromQuerySet
第二个参数:指定创建类的父类,使用元祖是因为支持多继承
第三个参数:指定创建类拥有的属性和方法,即class_dict

最终返回新创建的类作为Manager的父类

因为拷贝了QuerySet类的部分方法,所以可以调用Author.objects.all()等方法

相关文章

网友评论

      本文标题:ORM-model类.objects分析

      本文链接:https://www.haomeiwen.com/subject/fmgcfktx.html