Skip to content

Manager

Managers are the descriptor layer between model classes and querysets.

The default query manager is how most code enters the ORM, but custom managers are also the standard way to package reusable queryset defaults or project-specific query helpers.

Descriptor behavior

Managers are class-aware and instance-aware:

  • on a model class, the manager is bound to the class
  • on a model instance, the manager is shallow-copied and bound to that instance

That instance binding is what allows schema-aware or database-aware managers to follow an instance context without mutating the class-level manager.

Typical customization

class ActiveUsers(saffier.Manager):
    def get_queryset(self) -> saffier.QuerySet:
        return super().get_queryset().filter(is_active=True)


class User(saffier.Model):
    query: ClassVar[saffier.Manager] = saffier.Manager()
    active: ClassVar[ActiveUsers] = ActiveUsers()

saffier.Manager

Manager(
    model_class=None,
    *,
    owner=None,
    inherit=True,
    name="",
    instance=None,
)

Bases: BaseManager

Default manager descriptor for Saffier models.

A manager is both a descriptor and a queryset factory. Accessing it on a model class returns a class-bound manager; accessing it on an instance returns a shallow copy bound to that instance so schema and database context can follow the instance.

Examples:

class PublishedManager(saffier.Manager): def get_queryset(self) -> saffier.QuerySet: return super().get_queryset().filter(is_published=True)

Source code in saffier/core/db/models/managers.py
24
25
26
27
28
29
30
31
32
33
34
35
36
def __init__(
    self,
    model_class: Any = None,
    *,
    owner: Any = None,
    inherit: bool = True,
    name: str = "",
    instance: Any = None,
) -> None:
    self.owner = owner if owner is not None else model_class
    self.inherit = inherit
    self.name = name
    self.instance = instance

queryset_class class-attribute instance-attribute

queryset_class = QuerySet

owner instance-attribute

owner = owner if owner is not None else model_class

inherit instance-attribute

inherit = inherit

name instance-attribute

name = name

instance instance-attribute

instance = instance

model_class property writable

model_class

__get__

__get__(instance, owner)
Source code in saffier/core/db/models/managers.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
def __get__(self, instance: Any, owner: Any) -> Any:
    self.owner = owner
    if instance is None:
        self.instance = None
        return self

    cached = instance.__dict__.get(self.name)
    if cached is not None:
        return cached

    manager = copy.copy(self)
    manager.owner = owner
    manager.instance = instance
    instance.__dict__[self.name] = manager
    return manager

get_queryset

get_queryset()

Build a queryset bound to the current model, instance, and schema context.

RETURNS DESCRIPTION
QuerySet

Queryset configured for the active model, schema, and

TYPE: QuerySet

QuerySet

database context.

RAISES DESCRIPTION
ImproperlyConfigured

If the manager is used on an abstract model.

Source code in saffier/core/db/models/managers.py
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def get_queryset(self) -> "QuerySet":
    """Build a queryset bound to the current model, instance, and schema context.

    Returns:
        QuerySet: Queryset configured for the active model, schema, and
        database context.

    Raises:
        ImproperlyConfigured: If the manager is used on an abstract model.
    """
    if getattr(self.model_class.meta, "abstract", False):
        raise ImproperlyConfigured("Cannot query abstract models.")
    schema = None
    database = getattr(self.model_class, "database", None)

    if self.instance is not None:
        if hasattr(self.instance, "get_active_instance_schema"):
            schema = self.instance.get_active_instance_schema()
        else:
            schema = getattr(self.instance, "__using_schema__", None)
        database = getattr(self.instance, "database", database)
    else:
        if hasattr(self.model_class, "get_active_class_schema"):
            schema = self.model_class.get_active_class_schema()
        else:
            schema = getattr(self.model_class, "__using_schema__", None)

    if schema is None:
        tenant = get_tenant()
        if tenant:
            set_tenant(None)
            schema = tenant
        else:
            schema = get_schema()

    if schema is not None:
        return self.queryset_class(
            self.model_class,
            using_schema=schema,
            table=self.model_class.table_schema(schema),
            database=database,
        )  # type: ignore[arg-type]

    return self.queryset_class(self.model_class, database=database)