def index3(request): # 查找文章題目中包含中國的文章分類 category = Category.objects.filter(article__title__contains='中國') print(type(Category.objects)) print(type(category)) # print(category.query) return HttpResponse("success!")
<class 'django.db.models.manager.Manager'>
<class 'django.db.models.query.QuerySet'>python
class Manager(BaseManager.from_queryset(QuerySet)): pass
# 在這裏沒有寫明BaseManager是繼承了哪一個類,默認狀況下就是繼承了objects。即爲class BaseManager(objects): class BaseManager: @classmethod # 傳進來的參數cls表明的是當前的類名BaseManager, # queryset_class:表明的是from_queryset()接收的值QuerySet,而class_name爲默認值None def from_queryset(cls, queryset_class, class_name=None): # 由於咱們的from_queryset()方法只接受一個參數,因此class_name爲None,知足if條件 if class_name is None: # class_name=BaseManagerFromQuerySet class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__) # type()函數能夠用來動態建立類:返回type(建立的類名:BaseManagerFromQuerySet,繼承的類:能夠是單繼承也能夠是多繼承,用元組表示:(cls,), class_dict) # class_dict:{ # '_queryset_class': QuerySet, # **cls._get_queryset_methods(QuerySet):表明的是調用當前類BaseManager的_get_queryset_methods()方法所獲得的返回值。一樣咱們能夠將鼠標放在_get_queryset_methods()方法上,ctrl+b查看方法的返回值。 } return type(class_name, (cls,), { '_queryset_class': queryset_class, **cls._get_queryset_methods(queryset_class), })
class BaseManager: @classmethod def _get_queryset_methods(cls, queryset_class): # create_method()方法中傳遞兩個參數name和method,返回的是manager_method, 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 = {} # 遍歷QuerySet的函數,找到name和method for name, method in inspect.getmembers(queryset_class, predicate=inspect.isfunction): # Only copy missing methods. # hasattr(cls,name)返回的對象是否具備給定名稱的屬性,若是返回值爲True就繼續如下操做 if hasattr(cls, name): continue # 拷貝公共的方法或者是屬性queryset_only=False的方法。 # 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. # 在這裏咱們能夠將鼠標放在create_method()方法上,ctrl+b,查看該方法執行的操做:返回了一個manager_method(manager方法名)被賦值給new_methods new_methods[name] = create_method(name, method) # 將拷貝的多個函數都返回給new_methods,而且返回new_methods. # 此時的_get_queryset_methods(QuerySet)的返回值就是拷貝的多個QuerySet的方法。 return new_methods
# class_dict:{ # '_queryset_class': QuerySet, # **cls._get_queryset_methods(QuerySet):獲得拷貝的QuerySet的多個方法 # }
class Manager(BaseManager.from_queryset(QuerySet)): pass