---
url: "https://vueda.dev/v3/reference/api/py/vueda.core.models/FormattedNameManager.md"
title: "FormattedNameManager"
---

# FormattedNameManager

## Overview

Default manager for ``FormattedNameBaseModel``, which annotates ``formatted_name`` onto every
queryset of a model that reaches its formatted name through
``formatted_name_lookup_expression``.

A model with a ``formatted_name`` ``GeneratedField`` has that column already, so this manager
annotates nothing for it (see ``formatted_name_annotation_path``). One that computes the value in
Python with ``get_formatted_name()`` has no database path to annotate either, but may still
declare ``formatted_name_select_related``, which this manager applies the same as
``annotate_formatted_name`` does everywhere else. The annotation itself only matters for the third
form, where ``formatted_name`` is a name for some other path — a column on this model, or one
reached through single-valued relations.

Annotating here rather than only in ``VuedaViewSet.get_queryset`` is what makes
``formatted_name`` usable everywhere a queryset is, not just on a list request:
``Meta.ordering = ["formatted_name"]`` compiles, a ``ModelChoiceFilter`` rendering its choices
sorts by it, and a management command, a reverse relation, ``dumpdata``, or the admin sees the
same value the API does. Without it, ordering declared on the model would raise ``FieldError``
on every queryset the viewset didn't build.

**Replacing the default manager.** Django uses the first manager declared on a model as its
default, so a model that declares its own ``objects`` shadows this one and loses the annotation.
Subclass this manager rather than ``models.Manager`` when a VUEDA model needs a manager of its
own::

    class WidgetManager(FormattedNameManager):
        def get_queryset(self):
            return super().get_queryset().filter(archived=False)

    class Widget(VuedaModel):
        formatted_name = None
        formatted_name_lookup_expression = "label"

        objects = WidgetManager()

The same applies to a manager built with ``Manager.from_queryset()``: pass
``FormattedNameManager`` as the base (``FormattedNameManager.from_queryset(WidgetQuerySet)``).
A manager built with ``QuerySet.as_manager()`` has no base to pass. Replace
``WidgetQuerySet.as_manager()`` with ``FormattedNameManager.from_queryset(WidgetQuerySet)()``,
which builds the same manager on top of this one.

A manager declared on an abstract base shadows this one just as readily, and is the easier case
to miss, since the model that names a lookup expression can be several classes away from the one
that names the manager. ``VUEDAUserManager`` sits on a model with a ``formatted_name`` column,
and ``SentItemManager`` on one that computes it with ``get_formatted_name()``, so neither has an
annotation to lose.

**Every manager needs the annotation, not only the default.** A second manager, such as
``unfulfilled = UnfulfilledOrderManager()``, builds querysets of its own. Ordering or filtering
them by ``formatted_name`` raises ``FieldError`` unless that manager annotates it too. The
``vueda_core.E019`` system check reports each manager that does not, by name, rather than leaving
it to fail at query time. It checks every installed model, whether or not anything registered it.

**Opting a manager out.** Some managers never use ``formatted_name``. Examples are a manager that
feeds a data export, or one that sends data to or receives data from another system's API. When
the lookup expression crosses a relation, the annotation also adds a join that such a manager does
not want. Set ``used_without_formatted_name = True`` on the manager's class to leave it out of
``vueda_core.E019``::

    class OrderExportManager(models.Manager):
        used_without_formatted_name = True

    class Order(VuedaModel):
        formatted_name = None
        formatted_name_lookup_expression = "customer__name"

        objects = FormattedNameManager()
        export = OrderExportManager()

Declare ``objects`` above the opted-out manager. Django makes the first manager a model declares
its default, ahead of the ``objects`` this base provides, so a model that declares only ``export``
would make it the default manager. Setting ``Meta.default_manager_name = "objects"`` also works,
and then the order of the declarations does not matter.

Only the value ``True`` opts out. Subclasses inherit the attribute. A subclass that sets it back
to ``False`` is checked again.

The opt-out has no effect on the default manager. Related managers, the admin, and ``dumpdata``
all build their querysets from the default manager, so it always needs the annotation.

An opted-out manager still has to run with the model's ``Meta.ordering``. Django applies
``Meta.ordering`` to the querysets of every manager. When it names ``formatted_name``, every
query from an opted-out manager raises ``FieldError``, even a plain ``all()``. The
``vueda_core.E020`` system check reports that manager. Give its ``get_queryset()`` an
``order_by()`` of its own, or give it the annotation.

A viewset built on an opted-out manager still returns ``formatted_name``, because
``VuedaViewSet.get_queryset`` adds the annotation itself. A model that VUEDA never displays can
inherit Django's ``models.Model`` instead, and no ``formatted_name`` check runs on it. The guide
"Data That VUEDA Does Not Display" compares the two options.

**The base manager is not this manager.** Django builds ``Model._base_manager`` itself, as a
plain ``models.Manager``, unless ``Meta.base_manager_name`` names one — so it carries no
``formatted_name`` annotation even on a model whose ``objects`` is this manager. That is
deliberate on Django's part: the base manager is what fetches related objects, precisely because
a default manager may filter them out, and Django doesn't use it when querying *on* a related
model.

A model with a ``Meta.ordering`` naming ``formatted_name`` is the one that has to care, since a
base-manager queryset carrying that ordering has no annotation to sort and raises ``FieldError``.
Anything reached through ``get()`` is safe, because ``get()`` clears ordering: ``refresh_from_db``
and dereferencing a foreign key both go that way, and so do ``select_related`` and
``prefetch_related``, which order by nothing of the related model's own. What is *not* safe is a
base-manager queryset that gets evaluated as a whole, which is the related-object collection a
cascade delete performs (``Collector.related_objects`` returns a plain ``_base_manager``
queryset, which ``Collector.collect`` evaluates without clearing ordering). ``dumpdata --all``
reads the base manager but replaces the ordering with the primary key, so it is safe too. Set
``Meta.base_manager_name = "objects"`` on a model that needs those paths to work, which makes
Django use this manager for them too. Ordering by the lookup expression's own path instead of by
``formatted_name`` avoids the problem without touching the base manager. The
``vueda_core.E017`` system check reports a model that ordered by ``formatted_name`` and did
neither, so the failure surfaces at startup rather than on a delete.

## `get_queryset` {#get_queryset}

Return a new QuerySet object. Subclasses can override this method to
customize the behavior of the Manager.

### Signature {#get_queryset-signature}

`get_queryset(self)`

#### Parameters {#get_queryset-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| self |  | yes |  |  |

### Source {#get_queryset-source}

`server/vueda/core/models.py:286`

## Source

`server/vueda/core/models.py:171`
