Skip to content

info.checks

Classes

_comparable_ordering

An ordering rendered as directional field paths that can be compared with another ordering's, or None when a term in it has no single path to compare.

Two orderings sort the same way when they name the same paths, in the same sequence, each in the same direction — so each term becomes its path with a - for descending, and the sequence is compared as a whole. A path is resolved through formatted_name_lookup_expression first, since a formatted_name and the column behind it are one sort under two names, and a declaration is free to use either.

None is the answer for an ordering this can say nothing about, so a caller stays quiet rather than guessing. A term reads no column at all ("?", Now()) or more than one (Concat("first_name", "last_name")), and neither has a path that stands for the sort it performs — the same terms model_ordering.default withholds, for the same reason.

Direction is part of the comparison because reversing it is the one difference that shows up in every row of a response while looking like agreement in a diff: queued and -queued name the same field and sort the opposite way.

Signature

_comparable_ordering(model, ordering)

Parameters

NameTypeRequiredDescription
modelyes
orderingyes

Source

server/vueda/info/checks.py:564

_format_ordering_terms

The comparable paths of an ordering, quoted for a check message.

Signature

_format_ordering_terms(names)

Parameters

NameTypeRequiredDescription
namesyes

Source

server/vueda/info/checks.py:607

_formatted_name_is_python_only

Return True when the model's formatted_name is computed by get_formatted_name(), leaving the database nothing to sort by: no formatted_name column of its own, and no formatted_name_lookup_expression for VuedaViewSet.get_queryset to annotate onto the queryset.

Signature

_formatted_name_is_python_only(model)

Parameters

NameTypeRequiredDescription
modelyes

Source

server/vueda/info/checks.py:233

_get_field_model_info_corrected_fields

Build the model_fields metadata dict a real /info/ request would see for this serializer, including whatever get_field_model_info corrects -- so the check can tell a field the developer has already described (its real type_db/type_model filled in) from one that is still genuinely unresolved. Never raises: this feeds an advisory check, so a serializer this cannot safely introspect just yields no corrections rather than blocking manage.py check.

Signature

_get_field_model_info_corrected_fields(serializer_class, serializer_instance)

Parameters

NameTypeRequiredDescription
serializer_classyes
serializer_instanceyes

Source

server/vueda/info/checks.py:735

_is_property_on_model

Return True if attr_name is defined as a @property anywhere in the model's MRO.

Signature

_is_property_on_model(model, attr_name)

Parameters

NameTypeRequiredDescription
modelyes
attr_nameyes

Source

server/vueda/info/checks.py:24

_names_formatted_name

Return True when an ordering/ordering_fields/Meta.ordering declaration names formatted_name.

Signature

_names_formatted_name(ordering)

Parameters

NameTypeRequiredDescription
orderingyes

Source

server/vueda/info/checks.py:252

_queryset_annotation_names

The annotations a viewset's own queryset carries, which are orderable without being model fields.

None when the queryset can't be built at check time — a get_queryset that reaches for self.request raises here, and without knowing its annotations a term can't be judged.

Signature

_queryset_annotation_names(viewset)

Parameters

NameTypeRequiredDescription
viewsetyes

Source

server/vueda/info/checks.py:314

_validate_default_manager

Report a model that needs the formatted_name annotation but whose default manager won't add it.

FormattedNameManager is what puts formatted_name on every queryset of a model that reaches the value through formatted_name_lookup_expression, and Django uses the first manager in Meta.managers order as the default — so a model declaring its own objects shadows the one FormattedNameBaseModel provides and silently loses the annotation. Nothing fails at import time; instead formatted_name stops resolving on every queryset that manager builds, which is every queryset except the ones VuedaViewSet.get_queryset annotates for itself.

That matters most for a model whose Meta.ordering names formatted_name, which would raise FieldError on every query rather than only where the name is used. FormattedNameBaseModel._check_ordering asks about the default manager itself before withholding that term from Django's models.E015, so such a model is reported whether or not it is registered — this check adds a hint aimed at the manager rather than at the ordering, and covers the models whose Meta.ordering names something else while filtering and ordering by formatted_name outside a request break just the same.

A manager declared on an abstract base counts as much as one declared on the model, and is the easier case to miss, since the model naming the lookup expression may be several classes away from the one naming the manager.

Signature

_validate_default_manager(model)

Parameters

NameTypeRequiredDescription
modelyes

Source

server/vueda/info/checks.py:71

_validate_formatted_name_ordering

Report ordering declared on a formatted_name that only exists in Python.

A get_formatted_name() method is computed per object, so there is no column or annotation for the database to sort by, and sorting in Python would mean loading every row of the table.

include_model_ordering is how the caller keeps Meta.ordering from being reported once per registration. The viewset half has to run for every registration, because two viewsets on the same model can declare different orderings, but the model half is the same answer every time.

Signature

_validate_formatted_name_ordering(model, viewset, include_model_ordering)

Parameters

NameTypeRequiredDescription
modelyes
viewsetyes
include_model_orderingyes

Source

server/vueda/info/checks.py:271

_validate_lookup_expression_path

Report a formatted_name_lookup_expression that reaches through a multi-valued relation.

The expression names the database path VUEDA annotates as formatted_name — on every queryset the model builds, through FormattedNameManager, and on the ones a viewset builds, through VuedaViewSet.get_queryset. Annotating across a reverse foreign key, a many-to-many, or a GenericRelation joins a row per related object, so the model would silently return more rows than its table holds, everywhere, with no error to trace it back to the declaration. A single-valued relation is fine at any depth, nullable or not.

A path that doesn't resolve at all is left alone here. It fails loudly the first time a queryset is built, and it isn't what this check is for.

Signature

_validate_lookup_expression_path(model, lookup_expression)

Parameters

NameTypeRequiredDescription
modelyes
lookup_expressionyes

Source

server/vueda/info/checks.py:32

_validate_nulls_ordering

Report a viewset's nulls_ordering entries that name no usable nulls placement.

VuedaOrderingFilter turns a placement into the nulls_first/nulls_last keyword of F().asc()/F().desc(), so only "first" and "last" have a keyword to become. Anything else is ignored at request time rather than raising, which keeps a list endpoint working but silently drops the placement the declaration asked for — so the declaration is what gets reported.

nulls_ordering_flip names fields rather than placements, and a name in it that nulls_ordering doesn't cover simply has no placement to flip, so it is reported here too: it means the pair was meant to work together and one half is missing.

Both declarations are validated on every run, and every problem found in either is reported. The two are separate attributes that fail independently, so stopping at the first would hide the rest of the work behind however many manage.py check runs it took to walk them one at a time. An unusable nulls_ordering is read as giving no field a placement, which is what it does, so each nulls_ordering_flip entry is then reported as having nothing to flip — accurate, and it goes away with the one fix that caused it.

Signature

_validate_nulls_ordering(viewset)

Parameters

NameTypeRequiredDescription
viewsetyes

Source

server/vueda/info/checks.py:458

_validate_ordering_declarations

Report a viewset's ordering/ordering_fields terms that name no orderable path.

Django's own models.E015 already covers a model's Meta.ordering, but nothing covers the same drift on a viewset, where it is just as easy: a field renamed or removed leaves the declaration behind. What happens next depends on which attribute holds the stale term. An ordering term fails every list request that doesn't override it with ?o=, because DRF hands a viewset's default ordering to order_by() without validating it. An ordering_fields entry fails nothing at all: the model-info metadata leaves it out of the fields it advertises, so no client is offered it, and DRF only raises if one asks for that exact name anyway. That one is silent everywhere, which is what this check is for.

Signature

_validate_ordering_declarations(model, viewset)

Parameters

NameTypeRequiredDescription
modelyes
viewsetyes

Source

server/vueda/info/checks.py:328

_validate_queryset_ordering

Report a viewset whose class-level queryset orders by something its declarations don't.

DRF's OrderingFilter reads a view's ordering and nothing else. When that isn't declared it applies no ordering at all, so an order_by() on the viewset's queryset survives the filter backends and orders the response — while model_ordering.default, which reports ordering falling back to the model's Meta.ordering, describes an ordering that request never applied. The rows and the metadata disagree, and nothing in a passing test suite has to notice.

This reads the queryset class attribute only, never get_queryset(). A class attribute is a declaration, which is the kind of thing a check can hold to account: it is the same object on every request, so what it orders by either matches the declared default or doesn't. An ordering applied inside get_queryset(), in a manager, or in a helper is deliberately out of scope — calling get_queryset() here would run application code with no request behind it, and its result can vary per request anyway, so a check could confirm nothing about it. What this cannot see is left to the documentation (see the "Queryset Ordering" section of docs/core-concepts/filtering-and-ordering-semantics.md).

Three shapes get three messages, because the fix differs:

  • ordering is declared and disagrees. The declaration wins on every list request, so the metadata is accurate and the queryset's ordering is dead weight that reads as if it were in force.
  • ordering is absent and the model's Meta.ordering disagrees. The queryset's ordering is what arrives and the model's is what gets reported.
  • Neither is declared. The queryset's ordering is what arrives and the metadata reports no default ordering at all.

An ordering either side of the comparison has no single path for — "?", a multi-column expression — is not judged, since there is nothing to compare it against with any confidence.

Signature

_validate_queryset_ordering(model, viewset)

Parameters

NameTypeRequiredDescription
modelyes
viewsetyes

Source

server/vueda/info/checks.py:612

Report a model that declares both formatted_name_lookup_expression and formatted_name_select_related.

formatted_name_select_related only has an effect alongside get_formatted_name(): a lookup expression resolves formatted_name entirely through the database annotation, so there is no per-instance Python method for a select_related to prepare relations for. Declaring both suggests the model meant to use one and left the other behind.

_validate_select_related_pairing(model)

NameTypeRequiredDescription
modelyes

server/vueda/info/checks.py:129

Source

server/vueda/info/checks.py

Documents matching: server v3.0.0a1.post1client v3.0.0-alpha.2