Skip to content

Configuration Options

Complete alphabetical reference of all available configuration options with defaults, accepted values, and descriptions.

Types are shown next to each setting name. Accepted values is the contract for each setting. None means the setting is left unset unless the row says otherwise.

For the mental model behind the option groups, see PowerCRUD Concepts.

Core Configuration

Setting Accepted values Default When unset Description Reference
action_button_classes (str) str "" Buttons keep the selected pack's built-in classes Additional CSS classes for the View/Edit/Delete buttons. Values are not translated between frameworks. Template Packs
base_template_path (str) non-empty str None (required) Invalid when unset; must point at your project’s base template Template path PowerCRUD inherits from (your site chrome). There is no bundled base layout. Setup & Core CRUD basics
bulk_async (bool) True, False False Bulk actions run synchronously Enable asynchronous processing for bulk operations. Bulk editing (async)
bulk_async_allow_anonymous (bool) True, False True Anonymous users may trigger async jobs Require authentication for async bulk operations by setting to False. Bulk editing (async)
bulk_async_backend (str) str 'q2' Uses the django-q2 backend Backend identifier for async processing. Bulk editing (async)
bulk_async_conflict_checking (bool) True, False True Conflict locks are validated before queuing Toggle optimistic locking for async bulk edits. Bulk editing (async)
bulk_async_notification (str) str; common values: 'status_page', 'email', 'messages' 'status_page' Users are redirected to the status page Notification mechanism for async jobs. Bulk editing (async)
bulk_update_persistence_backend_config (dict) None or dict[str, Any] None No backend-specific config is passed Optional config payload passed into the configured bulk update persistence backend constructor. Bulk editing (async)
bulk_update_persistence_backend_path (str) None or import path str None PowerCRUD uses the built-in bulk update implementation Optional import path for a worker-safe bulk update persistence backend. When configured, the default sync bulk path and async bulk worker both delegate through it. Bulk editing (async)
bulk_delete (bool) True, False False Bulk delete buttons are hidden Enable bulk delete functionality. Bulk editing (synchronous)
bulk_fields (list[str]) list[str] [] Bulk edit form is disabled Editable model fields exposed in the bulk edit form. Non-editable fields and queryset annotation names raise a configuration error. Bulk editing (synchronous)
bulk_full_clean (bool) True, False True Each object runs full_clean() during bulk edits Skip expensive validation by setting to False. Bulk editing (synchronous)
bulk_min_async_records (int) int 20 Async path activates when at least 20 rows are selected Threshold for switching from sync to async bulk operations. Bulk editing (async)
bulk_modal_presentation (dict) Partial modal_presentation mapping None Uses modal_presentation Portable override for the built-in Bulk Edit dialog. Setup & Core CRUD basics
bulk_modal_box_classes (str) None or str None Uses modal_box_classes Deprecated. Framework-specific replacement classes for the built-in Bulk Edit dialog; emits FutureWarning and is targeted for removal in v1.0. Deprecations
column_alignments (dict[str, str]) None or dict[str, 'left' \| 'center' \| 'right'] None Rendered list body cells use the built-in type-based alignment heuristic Override list body-cell alignment for specific rendered fields or properties by name. Unconfigured columns keep the default heuristic. Setup & Core CRUD basics
column_help_text (dict[str, str]) None or dict[str, str] None Column headers render without help icons Add plain-text help tooltips to specific list headers by field/property name. Only configured columns show the adjacent info trigger. Setup & Core CRUD basics
column_sort_fields_override (dict[str, str]) None or dict[str, str] None Sortable list columns use their own field names, except direct relations with a concrete name field which default to field__name Override the queryset order_by() expression used when a visible list column header is clicked. Keys are visible column names, including queryset annotation fields; values are Django ordering expressions such as "author__name" or "customer__code". Setup & Core CRUD basics
column_value_formats (dict[str, str]) None or dict[str, 'date' \| 'time' \| 'datetime'] None Temporal model fields use their type defaults Override a named DateTimeField or typed temporal queryset annotation. DateField accepts only date, TimeField only time, and DateTimeField all three. Properties and annotations without an inferable temporal output_field are invalid. Setup & Core CRUD basics
default_datetime_value_format (str) 'date', 'time', 'datetime' 'date' DateTimeField columns show date-only output View-wide fallback for unconfigured DateTimeField and typed datetime-annotation list columns. Named column_value_formats entries take precedence. Set Django DATE_FORMAT, TIME_FORMAT, and DATETIME_FORMAT to control the rendered values; Django defaults apply when they are unset. Setup & Core CRUD basics
default_htmx_target (str) str '#content' Responses target the main content container Default HTMX target selector (ignored when HTMX is off). Setup & Core CRUD basics
default_filterset_fields (list[str]) None or list[str] None All allowed filters render immediately Limit the initially visible filter subset while keeping the remaining allowed filters available through the built-in Add filter control. Validated against effective filter names from the bound filter form. Filter controls
default_list_fields (list[str]) None or non-empty list[str] None Uses every allowed list column as the default visible set Optional default/reset subset for list options. Setting it also enables list options for backward compatibility. Model fields, queryset annotation fields, and properties are supported. List Options
detail_exclude (list[str]) list[str] [] Detail view mirrors the resolved detail_fields Remove specific fields from the detail layout. Setup & Core CRUD basics
detail_fields (list/str) None, '__all__', '__fields__', list[str] '__fields__' Inherits model fields from the list view Model fields rendered on the detail page. Queryset annotation names are list/filter columns and are not accepted as explicit detail fields. Setup & Core CRUD basics
field_labels (dict[str, str]) None or dict[str, str] None Labels use model verbose_name metadata or raw-name fallbacks Override display labels for named fields/properties across list headers, list options, forms, inline editing, display-only form items, and bulk edit labels. Explicit labels render exactly. Setup & Core CRUD basics
detail_properties (list/str) None, '__all__', '__properties__', list[str] [] No properties appear on the detail page Add computed properties to the detail view. Setup & Core CRUD basics
detail_properties_exclude (list[str]) list[str] [] All listed detail properties render Remove specific properties from the detail page. Setup & Core CRUD basics
dropdown_sort_options (dict) dict[str, str] {} PowerCRUD orders dropdowns by name/title/... heuristics Explicit ordering for dropdowns in filters, forms, and bulk edit widgets. Bulk editing (synchronous)
exclude (list[str]) list[str] [] Every concrete model field is shown Remove individual fields from the list view while keeping the rest. Setup & Core CRUD basics
extra_actions (list[dict \| PowerAction]) list[action spec] [] Only the default action buttons render Define extra per-row actions (URL, label, attributes). Modal actions may set partial modal_presentation, refresh_list_on_modal_close, hidden_if, disabled-state hooks, and permission affordance fields. Complete Example
extra_actions_mode (str) 'buttons', 'dropdown' 'buttons' Extra row actions render as visible buttons after the standard actions Control how row-level extra_actions are rendered. Use 'dropdown' to keep View/Edit/Delete visible and move only the extra row actions into a More overflow menu. Setup & Core CRUD basics
extra_actions_dropdown_open_upward_bottom_rows (int) int >= 0 3 All More menus open downward In dropdown mode, open the More menu upward for the last N rendered rows on the current page. Set 0 to disable this behavior. Setup & Core CRUD basics
extra_button_classes (str) str "" Extra buttons use the default button styling Additional CSS classes shared by every entry in extra_buttons. Styling & Tailwind
extra_button_selection_controls_disabled (bool) True, False False Selection-aware extra buttons can render row selection controls Set to True if the button uses selected rows, but this list should not show checkboxes just because of that button. Bulk edit and bulk delete still show checkboxes because they need them. Setup & Core CRUD basics
extra_buttons_mode (str) 'buttons', 'dropdown' 'buttons' Extra header buttons render as visible toolbar buttons Control how list-level extra_buttons are rendered. Use 'dropdown' to move configured extra buttons into a top toolbar More menu. Setup & Core CRUD basics
extra_buttons (list[dict \| PowerButton]) list[button spec] [] No extra header buttons are shown Add top-of-page buttons (e.g., custom actions, links). Buttons with uses_selection=True can render row selection controls even when built-in bulk edit/delete is not configured and clear the persisted selection after a successful HTMX request by default. Set clear_selection_on_success=False for read-only summary or preview buttons that should preserve selection. Modal buttons may set partial modal_presentation, refresh_list_on_modal_close, and permission affordance fields. Complete Example
filter_favourites_enabled (bool) True, False False No saved-favourites toolbar is rendered Enable the optional saved favourites UI for this list view when the powercrud.contrib.favourites app is installed and powercrud.urls is mounted under the powercrud namespace. Saved Favourites
fields (list/str) None, '__all__', list[str] '__all__' All concrete model fields show in the list view Columns displayed in the list view. Explicit lists may contain model field names and queryset annotation names. Combine with exclude. Setup & Core CRUD basics
filter_null_fields_exclude (list[str]) list[str] [] Nullable auto-generated filters gain built-in null filtering Opt out specific filterset_fields from automatic null-filter controls. Filter controls
filter_queryset_options (dict) dict[str, filter spec] {} Filter dropdowns query the entire related table Restrict or pre-filter related dropdown options per field. Filter controls
filterset_class (FilterSet) None or FilterSet subclass None A dynamic FilterSet is generated from filterset_fields Provide a custom FilterSet subclass for complex filtering. Filter controls
filterset_fields (list[str]) list[str] [] No filter sidebar is rendered Model fields or queryset annotation names to include in the auto-generated filterset. Annotation filters require an inferable output_field. Filter controls
form_class (ModelForm) None or ModelForm subclass None PowerCRUD builds a ModelForm from form_fields Override the form entirely with a custom class. Form controls
form_fields (list/str) None, '__all__', '__fields__', list[str] None All editable detail_fields appear in the auto-generated form Editable model fields included when PowerCRUD generates the form class for you. Queryset annotation names are invalid because they are read-only. Ignored when form_class is set. Form controls
form_fields_exclude (list[str]) list[str] [] The auto-selected form fields render untouched Remove individual fields from the auto-generated form. Ignored when form_class is set. Form controls
form_display_fields (list[str]) list[str] [] No display-only context block is shown above forms Model fields to render as read-only context above update forms. Can include editable=False model fields. Form controls
form_disabled_fields (list[str]) list[str] [] Every update-form field stays editable Disable specific update-form inputs while keeping them visible on the form. Must reference fields present on the built form. Form controls
field_queryset_dependencies (dict \| None) None or dependency map None Select fields use their default queryset Declarative parent/child queryset scoping shared by regular forms and inline forms. Form controls
hx_trigger (str/int/float/dict) None, scalar trigger name, or trigger map None No HX-Trigger header is sent Custom HTMX triggers to fire after responses. Setup & Core CRUD basics
inline_edit_allowed (callable) None or predicate callable None Every row follows the standard permission checks Optional predicate to allow/block inline editing per row. Inline editing
inline_edit_always_visible (bool) True, False True Editable cells keep a subtle always-on hint Toggle whether inline-editable cells show a resting highlight before hover/focus. Setting this to False removes only the resting highlight; hover/focus highlighting still remains active. Inline editing
inline_edit_fields (list/str) None, '__all__', '__fields__', list[str] None Inline editing is disabled Editable model fields editable inline. Queryset annotation names and explicit non-editable fields raise a configuration error; after that validation, PowerCRUD still filters the list to fields present on the actual form, only rendered list columns become clickable inline cells, and the inline row reposts the rest of the full form as hidden inputs on save. Inline editing
inline_edit_highlight_accent (str) hex color #rgb or #rrggbb '#14b8a6' Inline editing uses the built-in teal accent Accent color used to derive the inline-edit resting, hover/focus, and active-row highlight shades. Hex input only. Inline editing
inline_save_refresh_policy (str) 'reset_if_filtered_out', 'keep_page', 'reset_page' 'reset_if_filtered_out' Successful inline saves refresh the current list page unless the saved row falls out of the active filters Control whether inline-save list refreshes preserve the current page query parameter or drop back to page 1. Filtering, sorting, and page_size are always preserved. Inline editing
inline_preserve_required_fields (bool) True, False True Stock inline rows already repost non-rendered fields; this remains a fallback for custom omissions Reuse the object’s existing values for required form fields when a custom inline POST still omits them. Inline editing
inline_edit_requires_perm (str) None or str None Inline editing shows for anyone who can edit the object Permission codename required before showing inline controls. Inline editing
list_cell_link_default_open_in (str) 'current', 'new', 'modal' 'new' Omitted list-cell open_in values open in a new browser context Optional view-wide default opening mode for declarative and hook-backed list-cell links. If omitted, PowerCRUD assumes 'new'. Explicit per-link open_in wins. Use 'modal' when internal drill-in links should preserve the current list context, or 'current' for normal same-page anchors. Setup & Core CRUD basics
list_options_enabled (bool) True, False, None None No column chooser unless default_list_fields is set Enable the session-backed Cols control without narrowing the default visible columns. Use with default_list_fields when the reset/default state should be a subset. Set False to explicitly disable list options on a view. List Options
link_fields (dict[str, str \| dict]) None or mapping of rendered field/property name to a view_name string or a dict with exactly one of view_name / url, plus optional pk_attr / open_in / modal_presentation None List cells render as plain text/value output Make selected rendered list cells clickable. String shorthand uses the named view plus a default pk source (<field>_id for relation fields, row pk otherwise). Dict form may reverse a Django view_name or use a static url. Omitted open_in values use list_cell_link_default_open_in, whose own omitted default is "new"; explicit values may be "current", "new", or "modal". Modal links may set partial modal_presentation; the legacy modal_box_classes is deprecated. Inline-editable cells are never linked. Setup & Core CRUD basics
list_cell_tooltip_fields (dict[str, str \| dict]) None, dict[str, str], dict[str, {"hook": str, "mode": "eager" \| "lazy"}], or deprecated list[str] None No semantic list-cell tooltips are rendered Map rendered list fields/properties to row-specific tooltip hook methods. String values are eager. Rich dict values may set mode="lazy" so PowerCRUD skips tooltip hook work during list render and resolves content only when the cell tooltip is hovered or focused. PowerCRUD only evaluates configured names that are actually visible in the current list and silently ignores configured names that are not rendered. Hook-backed semantic cell tooltip text may include newline characters for multiline display. The legacy list form is deprecated and eager-only. Lazy Evaluation
m2m_filter_and_logic (bool) True, False False Multi-select filters use OR logic Switch ManyToMany filters to AND logic. Filter controls
modal_presentation (dict) Partial semantic modal mapping Portable defaults Uses the canonical centered, viewport-bounded, body-scrolling dialog Portable control of size, exact maximum width/height, scroll ownership, fullscreen, and vertical alignment. Setup & Core CRUD basics
modal_body_classes (str) None or str DaisyUI legacy default Legacy class fallback Deprecated. Framework-specific classes for the modal content wrapper; emits FutureWarning and is targeted for removal in v1.0. Deprecations
modal_box_classes (str) None or str DaisyUI legacy default Legacy class fallback Deprecated. Framework-specific modal-box classes; emits FutureWarning and is targeted for removal in v1.0. Deprecations
modal_classes (str) None or str 'modal' Legacy class fallback Deprecated. Framework-specific modal-shell classes; emits FutureWarning and is targeted for removal in v1.0. Deprecations
modal_id (str) None or str None Falls back to 'powercrudBaseModal' DOM id of the modal element (without #). Setup & Core CRUD basics
modal_target (str) None or str None Falls back to 'powercrudModalContent' DOM id of the element that receives modal content. Setup & Core CRUD basics
model (Model) Django model class Required PowerCRUD cannot run without a model Django model class for the CRUD view. Setup & Core CRUD basics
namespace (str) None or str None URL names are generated without a namespace Set to match app_name when including the view in namespaced URLs. Setup & Core CRUD basics
page_size_all_enabled (bool) True, False True The page-size selector includes All, and ?page_size=all disables pagination Set False to remove All from the selector and make direct ?page_size=all requests fall back to paginate_by. Cannot be False when paginate_by = None. Setup & Core CRUD basics
page_size_options (list[int]) None or non-empty list[int] None Selector uses legacy numeric choices 5/10/25/50/100; direct positive integer ?page_size= values are accepted Explicit finite page-size choices for the selector. When set, direct ?page_size= values must be in this list or they fall back to paginate_by. Must include paginate_by when pagination has a finite default. Setup & Core CRUD basics
paginate_by (int) None or int 25 Lists render 25 rows per page Default page size for list views. Set None on a view to render every record by default, which requires page_size_all_enabled = True. Setup & Core CRUD basics
power_fields (list) None or list[PowerField \| PowerOverride] None Base Field Intent attributes are used directly Structured declarations for Field Intent. A PowerField view must not mix base Field Intent attributes in the same inheritance chain. PowerField Reference
properties (list/str) None, '__all__', list[str] [] No computed properties show in the list view Computed properties to display alongside fields. Setup & Core CRUD basics
properties_exclude (list[str]) list[str] [] Every listed property renders Remove individual properties from the list view. Setup & Core CRUD basics
searchable_selects (bool) None, True, False True Select widgets render as native <select> controls Enable Tom Select enhancement for eligible select fields in regular forms, inline editing, bulk edit forms, and filter forms. Form controls
show_bulk_selection_meta (bool) True, False True Bulk-selection metadata actions appear above the table when a selection exists Control the contextual bulk-selection action row independently of show_record_count. Bulk editing (synchronous)
show_record_count (bool) True, False False No results-count metadata is shown above the table Display a small status line above the list table showing the total filtered queryset size, or the current page slice plus total when pagination is enabled. Setup & Core CRUD basics
table_classes (str) str "" Tables use the selected pack's default classes Additional classes applied to the main table element. Values are not translated between frameworks. Template Packs
table_header_min_wrap_width (int) None or int None Matches table_max_col_width Minimum width (in ch) before header labels wrap. Styling & Tailwind
table_max_col_width (int) None or positive int None Columns clamp at 25ch Maximum column width (in ch) for list and inline edit layouts. Styling & Tailwind
table_max_height (int) int from 0 to 100 70 Table height is 70% of remaining viewport Percentage of remaining viewport height allocated to the table. Styling & Tailwind
table_pixel_height_other_page_elements (int/float) non-negative int or float 0 No extra offset is subtracted Pixels reserved for other fixed-height elements (e.g., navbars). Styling & Tailwind
templates_path (str) str None Uses the selected pack's template namespace Explicit base directory that replaces the selected pack namespace. Use only when your project owns a complete template root. Template Packs
template_override_path (str) str None No project-level template root Application template root tried after model-specific files and before templates_path. Missing files fall back to the selected pack unless template_override_complete is enabled. Template Packs
template_override_complete (bool) True, False False Direct nested includes use templates_path Set to True only for a complete app-level --all copy so direct nested includes use template_override_path too. Template Packs
url_base (str) str Model name Defaults to the model’s lowercase name URL slug used when generating routes (e.g., project-list). Setup & Core CRUD basics
use_crispy (bool) None, True, False None Auto-detects: True when crispy_forms is installed Toggle Crispy Forms rendering for generated forms. Configure the compatible Crispy integration and CRISPY_TEMPLATE_PACK in your application. Selecting and configuring
use_htmx (bool) None, True, False None HTMX is disabled Enable HTMX responses (modals, inline updates, partial refreshes). Setup & Core CRUD basics
use_modal (bool) None, True, False None Modals stay disabled Enable HTMX-driven modal forms (requires use_htmx = True). Setup & Core CRUD basics
view_help (dict) None or {"summary": str, "details": str, "default_open": bool, "color": str, "min_width": str} None No collapsed screen help is shown Render optional collapsed screen-level help below view_instructions and above the list toolbar. Content is escaped plain text; blank lines in details create paragraphs. Optional color accepts the portable semantic tokens base, primary, secondary, accent, neutral, info, success, warning, error, or hex. Optional min_width overrides the view default. Setup & Core CRUD basics
view_help_default_color (str) portable semantic colour or hex colour base Collapsed screen help uses the quiet base colour Default colour theme for view_help when the help dict does not provide color. Semantic and hex colours are rendered as subtle pack-native tints. Setup & Core CRUD basics
view_help_min_width (str) CSS size using px, rem, em, ch, or % 40rem Collapsed screen help is at least 40rem wide when space allows Minimum width floor for table-aligned screen help. The help block still clamps to the surrounding container. Setup & Core CRUD basics
view_instructions (str) None or non-empty str None No helper text is shown under the list heading Render plain-text helper copy directly beneath the visible list-page heading. Content is escaped and does not accept HTML. Setup & Core CRUD basics
view_title (str) None or non-empty str None The visible list heading uses verbose_name_plural Override the visible list-page heading without changing model metadata or other singular/plural UI copy. Setup & Core CRUD basics

Settings Configuration

All of the following keys live inside the optional POWERCRUD_SETTINGS dict in your Django settings. Every entry has a default; you only override what you need.

Setting Accepted values Default When unset Description Reference
ASYNC_ENABLED (bool) True, False False Async helpers remain inactive Master toggle for async features. Async Manager
BULK_MAX_SELECTED_RECORDS (int) positive int 1000 Bulk selections can grow to 1000 rows before PowerCRUD stops adding more matching records Global cap for the synchronous bulk-selection pipeline, including queryset-wide Select all ... and capped Add ... more from ... metadata actions. Usually keep this at or below Django's DATA_UPLOAD_MAX_NUMBER_FIELDS. Bulk editing (synchronous)
CACHE_NAME (str) str 'default' Uses Django’s default cache backend Cache alias used for conflict locks and progress entries. Async Manager
CONFLICT_TTL (int) int 3600 Locks expire after one hour Cache TTL (seconds) for conflict lock entries. Async Manager
PROGRESS_TTL (int) int 7200 Progress data expires after two hours Cache TTL (seconds) for async progress entries. Async Manager
CLEANUP_GRACE_PERIOD (int) int 86400 Completed tasks are eligible for cleanup after 24h Grace period before scheduled cleanup reclaims finished tasks. Async Manager
FILTER_FAVOURITE_USER_RESOLVER (str or callable) None, callable, or dotted import path str None Saved favourites are owned by request.user Optional resolver for the user who owns saved filter favourites. The resolver receives the request and should return the user used by favourites toolbar, save, apply, update, and delete behavior. Saved Favourites
MAX_TASK_DURATION (int) int 3600 Tasks longer than an hour are treated as stuck Threshold for flagging slow async jobs. Async Manager
CLEANUP_SCHEDULE_INTERVAL (int) int 300 Cleanup jobs should run roughly every 5 minutes Suggested cadence (seconds) for any periodic cleanup runner. Async Manager
POWERCRUD_TEMPLATE_PACK (str) absent, built-in alias daisyui, or template-pack declaration path absent Selects the supported DaisyUI default Select the complete template pack at process startup. Use powercrud.contrib.bootstrap5:template_pack for Bootstrap 5. Selecting and configuring
POWERCRUD_CSS_FRAMEWORK (str) str; bundled default: 'daisyUI' 'daisyUI' Retains the compatible DaisyUI styling path Legacy CSS-framework compatibility setting. It does not select an optional template pack such as Bootstrap. Selecting and configuring
TAILWIND_SAFELIST_JSON_LOC (str) str '.' Uses the current directory as the default output location File path for Tailwind safelist output (used by management commands). Styling & Tailwind

Filter controls

Fine-tune what users can filter and how options are presented by combining filterset_fields, default_filterset_fields, filter_queryset_options, dropdown_sort_options, filter_null_fields_exclude, and m2m_filter_and_logic.

filterset_fields vs filterset_class

filterset_fields and filterset_class are alternative strategies.

If you set filterset_class, it takes precedence and PowerCRUD does not auto-generate filters from filterset_fields.

These settings only shape the auto-generated filterset_fields path:

  • filter_queryset_options
  • filter_null_fields_exclude
  • m2m_filter_and_logic
  • filter-side dropdown_sort_options

These behaviors still apply to both generated and custom filtersets after the filterset exists:

  • default_filterset_fields
  • searchable_selects
  • HTMX widget attrs when use_htmx = True and the custom filterset exposes setup_htmx_attrs()

For custom filtersets, the recommended pattern is still to subclass HTMXFilterSetMixin when you want reactive filtering.

default_filterset_fields controls which allowed filters are visible on first render.

  • Leave it unset to keep the current behavior and show every allowed filter immediately.
  • Set it to a subset to keep the remaining allowed filters hidden behind the Add filter control.
  • PowerCRUD validates it against the effective filter names from the bound filter form, not only against raw model field names.
  • Hidden optional filters become visible automatically when they carry an active value in the URL.
  • Visible optional filters persist through the reserved visible_filters query parameter until the user removes them explicitly.

Nullable auto-generated filters behave differently by field type:

  • Nullable ForeignKey and OneToOneField filters keep a single dropdown and add an Empty only option near the top.
  • Nullable scalar filters such as CharField, TextField, DateField, TimeField, IntegerField, DecimalField, FloatField, and BooleanField gain a separate companion ... is empty boolean select.
  • Companion null controls are rendered immediately after their parent auto-generated filter field in the form.

Auto-generated model fields with choices render as dropdown filters and match the selected value exactly. Text fields without choices use icontains by default. There is no separate declarative setting to change that lookup expression field by field; use filterset_class when you need custom lookup expressions.

Queryset annotation filters

Generated filters may also target queryset annotation names:

from django.db.models import BooleanField, Case, Value, When


class BookQueueView(PowerCRUDMixin, CRUDView):
    model = Book

    def get_queryset(self):
        """Attach the public annotation name used by PowerCRUD config."""
        return super().get_queryset().annotate(
            long_book=Case(
                When(pages__gte=400, then=Value(True)),
                default=Value(False),
                output_field=BooleanField(),
            )
        )

    fields = ["title", "author", "pages", "long_book"]
    filterset_fields = ["author", "long_book"]

Rules:

  • The name in fields and filterset_fields must match the public annotate(...) keyword.
  • Use output_field on Case, Value, and complex expressions so PowerCRUD can infer the generated filter type.
  • Annotation fields are read-only list/filter/sort columns. Do not put them in form_fields, inline_edit_fields, or bulk_fields.
  • If you set filterset_class, it takes precedence and PowerCRUD does not auto-generate annotation filters.

filter_null_fields_exclude always matches the original field names listed in filterset_fields.

  • Use ["birth_date"], not ["birth_date__isnull"].
  • Excluding a nullable scalar field suppresses the generated companion ... is empty control.
  • Excluding a nullable relation field suppresses the merged Empty only option.

Example:

filterset_fields = ["owner", "published_date", "status"]
default_filterset_fields = ["owner"]
filter_null_fields_exclude = ["status"]

In that configuration, owner stays visible by default, while published_date and status remain allowed but optional. owner keeps one dropdown with Empty only, published_date gains a separate Published date is empty companion filter when added, and status gets no built-in null helper.

If you want title to use iexact or startswith instead of the generated icontains behavior, move that filter into a custom filterset_class.

Start with the Filtering & sorting walkthrough and the dropdown guidance in Bulk editing (synchronous).

Form controls

Override or refine the automatically generated forms with form_class, form_fields, form_fields_exclude, form_display_fields, form_disabled_fields, and field_queryset_dependencies, and enable Crispy Forms support via use_crispy. See the field/detail setup examples in Setup & Core CRUD basics, the dedicated Forms guide, and the complete view example in reference/complete_example.md.

Relationship Between form_class and PowerCRUD Form Parameters

form_class overrides PowerCRUD form generation.

If you set form_class, PowerCRUD does not use form_fields or form_fields_exclude to decide which editable fields appear on the form. Those two parameters are for auto-generated forms only.

PowerCRUD still applies its runtime form behavior after the custom form is built, including form_disabled_fields, form_display_fields, field_queryset_dependencies, dropdown_sort_options, searchable_selects, and use_crispy.

form_display_fields and form_disabled_fields solve two different problems:

  • form_display_fields adds a separate read-only Context block above update forms. Use it for contextual model data, including editable=False fields.
  • form_disabled_fields keeps a real form input visible but locked on update forms. Because PowerCRUD uses Django field disabling, submitted tampering is ignored and the existing instance value is preserved. This setting does not lock the same field in create forms or inline editing.

Dependent queryset scoping

Use field_queryset_dependencies for straightforward cases where one selectable child field should be filtered from another form field, or where a queryset-backed field should always be restricted to a fixed subset.

Example:

field_queryset_dependencies = {
    "genres": {
        "static_filters": {"is_active": True},
        "depends_on": ["author"],
        "filter_by": {"authors": "author"},
        "order_by": "name",
        "empty_behavior": "none",
    }
}

Supported keys:

  • static_filters Fixed queryset lookups that always apply to the field across regular forms, inline forms, and bulk edit dropdowns.
  • depends_on Parent form fields whose values drive the child queryset.
  • filter_by Mapping of child queryset lookups to parent form field names.
  • order_by Optional ordering applied after filtering.
  • empty_behavior "none" hides all child choices until the parent value is available. "all" leaves the queryset unfiltered when the parent value is empty.

Notes:

  • Static queryset rules apply to regular create/update forms, inline forms, and bulk edit dropdowns.
  • Dynamic dependency rules apply to regular create/update forms and inline forms through the same form pipeline.
  • Overriding get_bulk_choices_for_field() bypasses declarative static queryset rules for bulk.
  • PowerCRUD resolves parent values from bound form data first, then the current instance, then any initial form values.
  • Keep this for simple equality-style filtering on queryset-backed form fields. For complex business rules, continue using a custom form_class or view override.
  • filter_by maps child queryset lookups to parent form field names. The left-hand side is the lookup used against the child field queryset, while the right-hand side is the parent form field name.

Common mental model:

field_queryset_dependencies = {
    "child_field": {
        "static_filters": {"is_active": True},
        "depends_on": ["parent_field"],
        "filter_by": {"child_queryset_lookup": "parent_field"},
    }
}

That reads as: “restrict child_field choices first by any fixed filters, then by child_queryset_lookup=<value of parent_field> when a parent-driven rule exists”.

Worked examples:

field_queryset_dependencies = {
    "genres": {
        "depends_on": ["author"],
        "filter_by": {"authors": "author"},
    }
}
field_queryset_dependencies = {
    "cmms_asset": {
        "depends_on": ["cmms_property_asset_type_override"],
        "filter_by": {
            "property_asset_type_override": "cmms_property_asset_type_override",
        },
    }
}

For a full explanation of filter_by, migration from old inline-only configs, and regular-vs-inline behaviour, see Forms.

Header buttons

Use extra_buttons for list-level actions above the table.

extra_buttons_mode controls whether configured list-level buttons render directly in the toolbar or move into a compact overflow menu:

  • 'buttons' keeps the default behavior and renders every configured extra button visibly.
  • 'dropdown' keeps built-in actions such as Create outside the overflow and moves only configured extra_buttons into a top toolbar More menu.

Selection-aware buttons can opt into the current persisted PowerCRUD selection:

extra_buttons_mode = "dropdown"

extra_buttons = [
    {
        "url_name": "projects:summary-help",
        "text": "Summary Help",
        "display_modal": True,
        "refresh_list_on_modal_close": True,
        "modal_presentation": {"size": "wide"},
    },
    {
        "url_name": "projects:selected-summary",
        "text": "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.",
        "permission_check": "can_view_project_report",
        "permission_behavior": "hide",
    },
]

Notes:

  • uses_selection defaults to False.
  • selection_min_count defaults to 0.
  • selection_min_behavior accepts 'allow' or 'disable' and defaults to 'allow'.
  • modal_presentation is only used when display_modal=True; it merges with the view presentation while that button's modal is open. Omit it when the button should use the default dialog.
  • refresh_list_on_modal_close is only used when display_modal=True; prefer HX-Trigger: {"refreshTable": true} when the endpoint knows it changed data.
  • When uses_selection=True, the button endpoint should use the current persisted PowerCRUD selection.
  • clear_selection_on_success defaults to True when uses_selection=True and False otherwise. PowerCRUD clears the persisted selection after the button's successful HTMX request completes; failed requests leave the selection intact. Set clear_selection_on_success=False for summary or preview buttons that should preserve the user's selection.
  • A selection-aware extra_buttons entry can render row selection controls even when bulk_fields = [] and bulk_delete = False.
  • Set extra_button_selection_controls_disabled = True 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.
  • permission or permission_check hides or disables the button before selection-state checks run. permission_behavior defaults to "hide".
  • The endpoint should still validate selection size, permissions, and lock rules server-side.
Parameter Guide
Parameter Type What it does
url_name str Django URL name for the endpoint called by the header button.
text str Visible label rendered on the button.
button_class str Framework-specific button styling class such as btn-primary.
needs_pk bool Should usually stay False for header buttons because they are not tied to a single row.
display_modal bool Opens the response in the standard modal target when True.
modal_presentation dict Portable per-button modal override. It accepts the documented size, maximum dimension, scroll, fullscreen, and alignment keys.
refresh_list_on_modal_close bool Refreshes the current list partial when this modal button's dialog closes. Defaults to False; ignored unless display_modal=True.
htmx_target str HTMX target element to update for non-modal or custom-target flows.
extra_attrs str Raw HTML attributes appended to the button element.
extra_class_attrs str Additional CSS classes appended after the standard button classes.
uses_selection bool Declares that the endpoint should read the current persisted PowerCRUD selection.
clear_selection_on_success bool Clears the persisted selection after a successful HTMX request from a selection-aware button. Defaults to True when uses_selection=True, otherwise False; ignored unless uses_selection=True.
selection_min_count int Minimum selected-row count required before the button is considered ready.
selection_min_behavior 'allow' \| 'disable' Controls whether the button stays clickable or becomes disabled when the selected count is below selection_min_count.
selection_min_reason str Tooltip/help text shown when a selection-aware header button is disabled.
permission str Django permission string resolved through has_power_permission(permission, request, obj=None).
permission_check str Named view method with signature permission_check(request, obj=None).
permission_behavior 'hide' \| 'disable' Controls whether permission failure removes the button or renders it disabled. Defaults to 'hide'.
permission_denied_reason str Tooltip/help text used only when permission_behavior = 'disable'.

Row actions

Use extra_actions to add per-row actions beyond the built-in View, Edit, and Delete links. Entries may be Base API dictionaries or PowerAction declarations from powercrud.actions.

extra_actions_mode controls how those extra row actions are displayed:

  • 'buttons' keeps the legacy behavior and renders extra row actions as visible joined buttons.
  • 'dropdown' keeps the standard row actions visible and moves only extra_actions into a More dropdown.

Example:

extra_actions_mode = "dropdown"
extra_actions_dropdown_open_upward_bottom_rows = 3

extra_actions = [
    {
        "url_name": "sample:author-detail",
        "text": "View Again",
        "needs_pk": True,
        "display_modal": True,
        "permission_check": "can_view_author_again",
        "permission_behavior": "hide",
        "hidden_if": "should_hide_view_again",
        "hidden_if_mode": "lazy",
        "disabled_state": "get_view_again_disabled_state",
        "disabled_state_mode": "lazy",
        "refresh_list_on_modal_close": True,
        "modal_presentation": {"size": "extra_wide"},
    },
]

Notes:

  • The default is 'buttons' for backward compatibility.
  • extra_actions_mode affects only row extra_actions, not top-of-page extra_buttons.
  • In dropdown mode, the More trigger uses the framework’s extra_default button styling unless you override the framework styles.
  • extra_actions_dropdown_open_upward_bottom_rows counts from the bottom of the currently rendered rows after filtering and pagination.
  • Set extra_actions_dropdown_open_upward_bottom_rows = 0 to keep every dropdown opening downward.
  • modal_presentation is only used when display_modal=True; it merges with the view presentation while this row action's modal is open.
  • refresh_list_on_modal_close is only used when display_modal=True; prefer HX-Trigger: {"refreshTable": true} when the endpoint knows it changed data.
  • hidden_if is an optional view method name with signature (obj, request) -> bool. Return True to omit the action for that row. Hidden actions are removed before disabled hooks are evaluated.
  • Set hidden_if_mode = "lazy" only in extra_actions_mode = "dropdown" when the row relevance check is expensive and should be resolved when the row More menu opens. Button-mode actions keep eager hidden-if evaluation.
  • disabled_state is a single-hook alternative to disabled_if / disabled_reason. Return a non-empty string to disable the action and show that string as the reason; return None, False, or an empty string to keep it enabled.
  • Set disabled_state_mode = "lazy" only in extra_actions_mode = "dropdown" when the disabled reason is expensive to calculate and should be resolved when the row More menu opens. Button-mode actions keep eager disabled-state evaluation.
  • permission or permission_check hides or disables the action before hidden_if and disabled_state run. permission_behavior defaults to "hide".
  • disabled_if and disabled_reason are deprecated view method names used to disable a row action based on the current object and request. Use disabled_state instead.
  • Do not combine disabled_state with disabled_if or disabled_reason on the same action.
  • Use hidden_if when an action is not applicable for a row. Use disabled_state when the action is applicable but unavailable and needs an explanatory reason.
  • lock_sensitive remains available when an action should also disable under PowerCRUD's existing lock/blocked-row state.
Parameter Guide
Parameter Type What it does
url_name str Django URL name for the per-row endpoint that the action should call.
text str Visible label for the action button or dropdown entry.
needs_pk bool Usually True so the row primary key is included in the URL.
button_class str Styling class used when the action renders as a visible button.
display_modal bool Opens the response in the standard modal target when True.
modal_presentation dict Portable per-action modal override. It accepts the documented size, maximum dimension, scroll, fullscreen, and alignment keys.
refresh_list_on_modal_close bool Refreshes the current list partial when this modal action's dialog closes. Defaults to False; ignored unless display_modal=True.
htmx_target str HTMX target element to update for non-modal or custom-target flows.
hx_post bool Sends the action as an HTMX POST instead of the default GET when True.
lock_sensitive bool Disables the action automatically when PowerCRUD marks the row as blocked by its existing lock logic.
hidden_if str Name of a view method with signature (obj, request) -> bool that decides whether the action should be omitted for that row.
hidden_if_mode 'eager' \| 'lazy' Defaults to 'eager'. Use 'lazy' with dropdown row actions to resolve hidden_if when the row More menu opens.
disabled_state str Name of a view method with signature (obj, request) -> str \| None \| bool that returns a disabled reason string, or a falsey enabled value.
disabled_state_mode 'eager' \| 'lazy' Defaults to 'eager'. Use 'lazy' with dropdown row actions to resolve disabled_state when the row More menu opens.
disabled_if str Deprecated. Name of a view method with signature (obj, request) -> bool that decides whether the action is disabled for that row. Use disabled_state instead.
disabled_reason str Deprecated. Name of a view method with signature (obj, request) -> str \| None that returns the disabled tooltip/help text. Use disabled_state instead.
permission str Django permission string resolved through has_power_permission(permission, request, obj=obj).
permission_check str Named view method with signature permission_check(request, obj=None).
permission_behavior 'hide' \| 'disable' Controls whether permission failure removes the action or renders it disabled. Defaults to 'hide'.
permission_denied_reason str Tooltip/help text used only when permission_behavior = 'disable'.

See Permission-Aware Affordances for built-in Create/Detail/Edit/Delete permission hooks and backend enforcement boundaries.

Searchable select enhancement

PowerCRUD enhances eligible select dropdowns with Tom Select when searchable_selects = True (default).

  • Applies to regular create/update forms, inline row forms, bulk edit form selects, and filter form selects.
  • Single-select fields are enhanced as searchable dropdowns.
  • Inline single-selects focus when their row enters edit mode, but the dropdown stays closed until the user clicks or types.
  • Multi-select filter fields are enhanced as searchable multi-select controls.
  • Boolean-style selects remain native controls.
  • Preserves normal Django form POST semantics (the underlying <select> still submits the selected value).
  • When using the built-in daisyUI pack, package CSS overrides Tom Select with daisyUI semantic colors so controls follow the active theme.

Per-field opt-out is available via a view hook:

class BookCRUDView(PowerCRUDMixin, CRUDView):
    searchable_selects = True

    def get_searchable_select_enabled_for_field(
        self, field_name: str, bound_field=None
    ) -> bool:
        return field_name != "author"

Inline dependency controls

Use field_queryset_dependencies as the primary declaration when one inline field needs another field to be refreshed in the same row. PowerCRUD derives inline dependency wiring from that shared config automatically.

Example:

field_queryset_dependencies = {
    "genres": {
        "depends_on": ["author"],
        "filter_by": {"authors": "author"},
    }
}

Notes:

  • The child field must also be present in inline_edit_fields.
  • Parent fields listed in depends_on must be inline-editable too.
  • PowerCRUD handles the frontend refresh, widget swap, and child queryset restriction when the dependency is declared in field_queryset_dependencies.
  • PowerCRUD uses the standard ...-inline-dependency endpoint automatically.
  • Older inline-only dependency config is ignored. Move any remaining business rules into field_queryset_dependencies.

Migration sketch:

field_queryset_dependencies = {
    "cmms_asset": {
        "depends_on": ["cmms_property_asset_type_override"],
        "filter_by": {
            "property_asset_type_override": "cmms_property_asset_type_override",
        },
    }
}

See Forms for a fuller worked example.

Notes

  • Required settings: Only model and base_template_path are required.
  • Auto-detection: use_crispy auto-detects whether crispy_forms is installed; everything else is opt-in.
  • Dependencies: Bulk operations require both use_htmx = True and use_modal = True.
  • Detail permissions: Override has_power_detail_permission(request, obj) when the current user should not see the built-in Detail/View row action or call the PowerCRUD-owned detail endpoint.
  • Bulk permissions: bulk_fields and bulk_delete configure the operation surface. Override has_power_bulk_update_permission(request) or has_power_bulk_delete_permission(request) when the current user should not see or call those PowerCRUD-owned bulk operations.
  • Duplicate entries: Supported list-style config options quietly remove duplicates and keep the first occurrence.
  • Field shortcuts: Use '__all__' for all fields, '__fields__' to reference the fields setting.
  • Property shortcuts: Use '__all__' for all properties, '__properties__' to reference the properties setting.