Skip to content

Computed View Data (data_method)

By default a view gets its data by querying the model’s records through the standard data layer (fetchDatafilter → records): pagination, sorting, grouping, the search bar, the Browse panel and inline edit all flow from that one query.

Some views render data that isn’t a flat list of records — a capacity board (every resource × time bucket, with a computed load %), a reconciliation grid, a roll-up. For those, a view declares a data_method in its arch. This is the standard, blessed way a view sources computed / non-record data: the front end calls that method on the view’s model — passing the view’s live params — and renders the result, instead of running the record query.

It replaces the older pattern of building a bespoke client action per computed board (each of which bypassed the view system and hand-rolled its own header). With data_method, computed data flows through the view system, so the view inherits the standard chrome: the title bar, view switching, full-bleed layout.

  • Read-only. A method returns a computed projection. The generic record affordances (inline edit, record selection, export, form drill-down, pagination, the Browse panel) only apply if the method itself honours the params it is handed. A purely computed board declares those off (see Gating the chrome below).
  • The return contract is per view type, not universal. There is no single magic shape. Each view type documents what its data_method must return — e.g. List wants record-shaped rows, Calendar wants dated records, TimelineHeatmap wants a { buckets, rows } matrix. Any view type can opt in, with its own documented shape.

Put data_method in the view arch instead of (or alongside, where a view type allows a fallback) field mappings:

- data_type: UiView
name: wc_load_heatmap_view
identifier: wc_load_heatmap_view
type: TimelineHeatmap
model: WorkCenterLoad
arch:
- data_method: ui_load

The action points at the same (often transient) model:

- data_type: WindowAction
name: Capacity Load
identifier: mrp_capacity_load_action
model: WorkCenterLoad
default_view: wc_load_heatmap_view
modes: TimelineHeatmap
action_ctx:
data_method: ui_load # mirror — see "Gating the chrome"
views:
- - R
- - wc_load_heatmap_view

The method lives on the view’s model. For computed boards this is usually a transient read model (_transient = True) — it stores nothing; it just exposes the method. Because the /api/execute/<model>/<method> path instantiates an in-memory instance and calls method(instance, **kwargs), the method MUST be an instance method (self), not a cls method. The view’s live params arrive as keyword arguments matched by name.

class WorkCenterLoad(Model):
_transient = True
_verbose_name = "Work Center Load"
async def ui_load(self, bucket="Day", anchor=None):
# `bucket` and `anchor` are the TimelineHeatmap's live params.
...
return {"buckets": [...], "rows": [...]} # the view type's shape

self, not cls. A cls-first method is auto-promoted to a classmethod and the execute path’s positional instance collides with its first real argument (got multiple values for argument ...). Every data_method is a self instance method.

The front end passes the view’s current state as the method kwargs, so navigating (changing the period, paging the window) re-queries:

View typeParams passed
TimelineHeatmapbucket (Day/Week/Month), anchor (YYYY-MM-DD)

(Other view types add their own as they adopt the mechanism — e.g. a calendar window, a pivot groupby.)

A single shared hook implements the mechanism for every view type: app/src/hooks/useViewDataMethod.js. It calls executeMethod(model, method, [], params), returns { data, isLoading, isFetching, error }, keeps previous data while refetching, and background-polls. A view component branches on whether its arch declares data_method:

const computed = useViewDataMethod({
model: actionData.model,
method: arch.data_method,
params: { bucket, anchor },
enabled: !!arch.data_method,
});

Adopting data_method in a new view type is therefore three things: branch the component on arch.data_method, call useViewDataMethod with that view’s live params, and render the returned shape. No new plumbing per view.

A computed view has no records, so the search bar and Browse panel are meaningless. The action mirrors data_method into action_ctx; the shell reads actionData.ctx.data_method and drops both for that action only:

  • AppHeader / SecondaryHeader — no search bar.
  • ShellContent — no Browse FilterPanel.

This is gated per action, not per view type — so the generic record-sourced use of the same view type (e.g. a TimelineHeatmap over real records) keeps full search + Browse. Only the computed action loses them.