Skip to content

Structured API Recipes

These recipes compare the Base Configuration API with the Structured Declaration API for repeated field and action patterns.

Use them when direct class attributes or dictionaries are correct but have started to repeat the same intent across related views.

Reusable Field Intent

Use this when related CRUD views share most field roles, but one view needs a small local variation.

class ActionCRUDView(PowerCRUDMixin, CRUDView):
    model = Action
    base_template_path = "core/base.html"

    fields = ["status"]
    default_list_fields = ["status"]
    list_cell_tooltip_fields = {"status": "get_status_tooltip"}
    bulk_fields = ["status"]


class ActionReviewCRUDView(PowerCRUDMixin, CRUDView):
    model = Action
    base_template_path = "core/base.html"

    fields = ["status"]
    default_list_fields = ["status"]
    list_cell_tooltip_fields = {"status": "get_status_tooltip"}
    bulk_fields = []
from powercrud.powerfields import PowerField


ACTION_STATUS = PowerField(
    "status",
    default_list=True,
    tooltip_hook="get_status_tooltip",
    bulk=True,
)


class ActionCRUDView(PowerCRUDMixin, CRUDView):
    model = Action
    base_template_path = "core/base.html"

    power_fields = [
        ACTION_STATUS,
    ]


class ActionReviewCRUDView(PowerCRUDMixin, CRUDView):
    model = Action
    base_template_path = "core/base.html"

    power_fields = [
        ACTION_STATUS.with_options(bulk=False),
    ]

Use the structured version when the field's roles repeat across views and a local change such as bulk=False should be obvious at the declaration site.

Per-Field Column Presentation

Use this when a field needs a different list-column treatment from the view-wide policy. The policy remains a normal view setting; the Structured API carries only the named field override.

class AssetCRUDView(PowerCRUDMixin, CRUDView):
    model = Asset
    column_width_policy = "semantic"
    column_width_modes = {
        "asset_code": "compact",
    }

    fields = ["name", "asset_code", "last_reviewed"]
from powercrud.powerfields import PowerField


class AssetCRUDView(PowerCRUDMixin, CRUDView):
    model = Asset
    column_width_policy = "semantic"

    power_fields = [
        PowerField("name", default_list=True),
        PowerField(
            "asset_code",
            default_list=True,
            column={"width": "compact"},
        ),
        PowerField("last_reviewed", default_list=True),
    ]

Use column_width_policy = "semantic" when PowerCRUD should choose sensible widths from field type. Use column={"width": ...} only when your application knows that one named field needs a different mode. See Semantic column widths for the available modes and behaviour.

Reusable Row Actions

Use this when row actions share the same modal, disabled-state, or sizing behavior.

extra_actions = [
    {
        "text": "Workflow Action",
        "url_name": "cases:workflow-action",
        "needs_pk": True,
        "display_modal": True,
        "modal_presentation": {"size": "extra_wide"},
        "disabled_state": "get_workflow_action_disabled_state",
    },
    {
        "text": "Timeline",
        "url_name": "cases:timeline",
        "needs_pk": True,
        "display_modal": True,
        "modal_presentation": {"size": "extra_wide"},
    },
]
from powercrud.actions import PowerAction


ROW_MODAL = PowerAction(
    text="Workflow Action",
    url_name="cases:workflow-action",
    display_modal=True,
    modal_presentation={"size": "extra_wide"},
    disabled_state="get_workflow_action_disabled_state",
)

extra_actions = [
    ROW_MODAL,
    ROW_MODAL.with_options(
        text="Timeline",
        url_name="cases:timeline",
        disabled_state=None,
    ),
]

Use the structured version when action mechanics repeat and only text, endpoint, modal size, or disabled logic changes.

Selection-Aware Toolbar Buttons

Use this when toolbar buttons share the same selection rules.

extra_buttons = [
    {
        "text": "Selected Summary (Do Not Clear)",
        "url_name": "sample:book-selected-summary",
        "needs_pk": False,
        "display_modal": True,
        "uses_selection": True,
        "clear_selection_on_success": False,
        "selection_min_count": 1,
        "selection_min_behavior": "disable",
        "selection_min_reason": "Select at least one row first.",
    },
    {
        "text": "Selected Export",
        "url_name": "sample:book-selected-export",
        "needs_pk": False,
        "display_modal": True,
        "uses_selection": True,
        "selection_min_count": 1,
        "selection_min_behavior": "disable",
        "selection_min_reason": "Select at least one row to export.",
    },
]
from powercrud.actions import PowerButton


SELECTED_MODAL = PowerButton(
    text="Selected Summary",
    url_name="sample:book-selected-summary",
    display_modal=True,
    uses_selection=True,
    selection_min_count=1,
    selection_min_behavior="disable",
    selection_min_reason="Select at least one row first.",
)

extra_buttons = [
    SELECTED_MODAL,
    SELECTED_MODAL.with_options(
        text="Selected Summary (Do Not Clear)",
        clear_selection_on_success=False,
    ),
    SELECTED_MODAL.with_options(
        text="Selected Export",
        url_name="sample:book-selected-export",
        selection_min_reason="Select at least one row to export.",
    ),
]

Use the structured version when the selection contract repeats and the local difference should be limited to the label, URL, or reason text.

uses_selection=True can render row selection controls without enabling the built-in bulk edit/delete UI.

Set extra_button_selection_controls_disabled = True on the view if the button uses selected rows, but this list should not show checkboxes just because of that button.

This is mainly useful when the selected rows come from somewhere else, or when the page has its own custom way to choose rows. Bulk edit and bulk delete still show checkboxes because they need them.

What To Do Next