to retain order track each time a manager instance is created set to true for the objects managers that are automatically created if set to true the manager will be serialized into migrations and will thus be available in e g runpython operations capture the arguments to make returning them trivial return applabel modellabel managername return s s self model meta label self name def classgetitemcls args kwargs return cls def deconstructself qsclass self querysetclass if getattrself builtwithasmanager false using myqueryset asmanager return true asmanager none managerclass s s qsclass module qsclass name qsclass none args none kwargs else modulename self module name self class name make sure it s actually there and not an inner class module importmodulemodulename if not hasattrmodule name raise valueerror could not find manager s in s n please note that you need to inherit from managers you dynamically generated with fromqueryset name modulename return false asmanager s s modulename name managerclass none qsclass self constructorargs0 args self constructorargs1 kwargs def checkself kwargs return classmethod def getquerysetmethodscls querysetclass def createmethodname method wrapsmethod def managermethodself args kwargs return getattrself getqueryset nameargs kwargs return managermethod newmethods for name method in inspect getmembers querysetclass predicateinspect isfunction only copy missing methods if hasattrcls name continue only copy public methods or methods with the attribute querysetonlyfalse querysetonly getattrmethod querysetonly none if querysetonly or querysetonly is none and name startswith continue copy the method onto the manager newmethodsname createmethodname method return newmethods classmethod def fromquerysetcls querysetclass classnamenone if classname is none classname sfroms cls name querysetclass name return type classname cls querysetclass querysetclass cls getquerysetmethodsquerysetclass def contributetoclassself cls name self name self name or name self model cls setattrcls name managerdescriptorself cls meta addmanagerself def setcreationcounterself self creationcounter basemanager creationcounter basemanager creationcounter 1 def dbmanagerself usingnone hintsnone obj copy copyself obj db using or self db obj hints hints or self hints return obj property def dbself return self db or router dbforreadself model self hints proxies to queryset def getquerysetself return self querysetclassmodelself model usingself db hintsself hints def allself we can t proxy this method through the queryset like we do for the rest of the queryset methods this is because queryset all works by creating a copy of the current queryset and in making said copy all the cached prefetchrelated lookups are lost see the implementation of relatedmanager getqueryset for a better understanding of how this comes into play return self getqueryset def eqself other return isinstanceother self class and self constructorargs other constructorargs def hashself return idself class managerbasemanager fromquerysetqueryset pass class managerdescriptor def initself manager self manager manager def getself instance clsnone if instance is not none raise attributeerror manager isn t accessible via s instances cls name if cls meta abstract raise attributeerror manager isn t available s is abstract cls meta objectname if cls meta swapped raise attributeerror manager isn t available s has been swapped for s cls meta label cls meta swapped return cls meta managersmapself manager name class emptymanagermanager def initself model super init self model model def getquerysetself return super getqueryset none to retain order track each time a manager instance is created set to true for the objects managers that are automatically created if set to true the manager will be serialized into migrations and will thus be available in e g runpython operations capture the arguments to make returning them trivial return app_label model_label manager_name return a 5 tuple of the form as_manager true manager_class queryset_class args kwargs raise a valueerror if the manager is dynamically generated using myqueryset as_manager as_manager manager_class qs_class args kwargs make sure it s actually there and not an inner class as_manager manager_class qs_class args kwargs only copy missing methods only copy public methods or methods with the attribute queryset_only false copy the method onto the manager set the creation counter value for this instance and increment the class level copy proxies to queryset return a new queryset object subclasses can override this method to customize the behavior of the manager we can t proxy this method through the queryset like we do for the rest of the queryset methods this is because queryset all works by creating a copy of the current queryset and in making said copy all the cached prefetch_related lookups are lost see the implementation of relatedmanager get_queryset for a better understanding of how this comes into play
import copy
import inspect
from functools import wraps
from importlib import import_module

from django.db import router
from django.db.models.query import QuerySet


class BaseManager:
    
    creation_counter = 0

    
    auto_created = False

    
    
    use_in_migrations = False

    def __new__(cls, *args, **kwargs):
        
        obj = super().__new__(cls)
        obj._constructor_args = (args, kwargs)
        return obj

    def __init__(self):
        super().__init__()
        self._set_creation_counter()
        self.model = None
        self.name = None
        self._db = None
        self._hints = {}

    def __str__(self):
        
        return "%s.%s" % (self.model._meta.label, self.name)

    def __class_getitem__(cls, *args, **kwargs):
        return cls

    def deconstruct(self):
        
        qs_class = self._queryset_class
        if getattr(self, "_built_with_as_manager", False):
            
            return (
                True,  
                None,  
                "%s.%s" % (qs_class.__module__, qs_class.__name__),  
                None,  
                None,  
            )
        else:
            module_name = self.__module__
            name = self.__class__.__name__
            
            module = import_module(module_name)
            if not hasattr(module, name):
                raise ValueError(
                    "Could not find manager %s in %s.\n"
                    "Please note that you need to inherit from managers you "
                    "dynamically generated with 'from_queryset()'."
                    % (name, module_name)
                )
            return (
                False,  
                "%s.%s" % (module_name, name),  
                None,  
                self._constructor_args[0],  
                self._constructor_args[1],  
            )

    def check(self, **kwargs):
        return []

    @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
        ):
            
            if hasattr(cls, name):
                continue
            
            
            queryset_only = getattr(method, "queryset_only", None)
            if queryset_only or (queryset_only is None and name.startswith("_")):
                continue
            
            new_methods[name] = create_method(name, method)
        return new_methods

    @classmethod
    def from_queryset(cls, queryset_class, class_name=None):
        if class_name is None:
            class_name = "%sFrom%s" % (cls.__name__, queryset_class.__name__)
        return type(
            class_name,
            (cls,),
            {
                "_queryset_class": queryset_class,
                **cls._get_queryset_methods(queryset_class),
            },
        )

    def contribute_to_class(self, cls, name):
        self.name = self.name or name
        self.model = cls

        setattr(cls, name, ManagerDescriptor(self))

        cls._meta.add_manager(self)

    def _set_creation_counter(self):
        
        self.creation_counter = BaseManager.creation_counter
        BaseManager.creation_counter += 1

    def db_manager(self, using=None, hints=None):
        obj = copy.copy(self)
        obj._db = using or self._db
        obj._hints = hints or self._hints
        return obj

    @property
    def db(self):
        return self._db or router.db_for_read(self.model, **self._hints)

    
    
    

    def get_queryset(self):
        
        return self._queryset_class(model=self.model, using=self._db, hints=self._hints)

    def all(self):
        
        
        
        
        
        
        return self.get_queryset()

    def __eq__(self, other):
        return (
            isinstance(other, self.__class__)
            and self._constructor_args == other._constructor_args
        )

    def __hash__(self):
        return id(self)


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


class ManagerDescriptor:
    def __init__(self, manager):
        self.manager = manager

    def __get__(self, instance, cls=None):
        if instance is not None:
            raise AttributeError(
                "Manager isn't accessible via %s instances" % cls.__name__
            )

        if cls._meta.abstract:
            raise AttributeError(
                "Manager isn't available; %s is abstract" % (cls._meta.object_name,)
            )

        if cls._meta.swapped:
            raise AttributeError(
                "Manager isn't available; '%s' has been swapped for '%s'"
                % (
                    cls._meta.label,
                    cls._meta.swapped,
                )
            )

        return cls._meta.managers_map[self.manager.name]


class EmptyManager(Manager):
    def __init__(self, model):
        super().__init__()
        self.model = model

    def get_queryset(self):
        return super().get_queryset().none()