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_optionsfilter_null_fields_excludem2m_filter_and_logic- filter-side
dropdown_sort_options
These behaviors still apply to both generated and custom filtersets after the filterset exists:
default_filterset_fieldssearchable_selects- HTMX widget attrs when
use_htmx = Trueand the custom filterset exposessetup_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_filtersquery parameter until the user removes them explicitly.
Nullable auto-generated filters behave differently by field type:
- Nullable
ForeignKeyandOneToOneFieldfilters keep a single dropdown and add anEmpty onlyoption near the top. - Nullable scalar filters such as
CharField,TextField,DateField,TimeField,IntegerField,DecimalField,FloatField, andBooleanFieldgain a separate companion... is emptyboolean 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
fieldsandfilterset_fieldsmust match the publicannotate(...)keyword. - Use
output_fieldonCase,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, orbulk_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 emptycontrol. - Excluding a nullable relation field suppresses the merged
Empty onlyoption.
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_fieldsadds a separate read-onlyContextblock above update forms. Use it for contextual model data, includingeditable=Falsefields.form_disabled_fieldskeeps 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_filtersFixed queryset lookups that always apply to the field across regular forms, inline forms, and bulk edit dropdowns.depends_onParent form fields whose values drive the child queryset.filter_byMapping of child queryset lookups to parent form field names.order_byOptional 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_classor view override. filter_bymaps 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 configuredextra_buttonsinto a top toolbarMoremenu.
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_selectiondefaults toFalse.selection_min_countdefaults to0.selection_min_behavioraccepts'allow'or'disable'and defaults to'allow'.modal_presentationis only used whendisplay_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_closeis only used whendisplay_modal=True; preferHX-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_successdefaults toTruewhenuses_selection=TrueandFalseotherwise. PowerCRUD clears the persisted selection after the button's successful HTMX request completes; failed requests leave the selection intact. Setclear_selection_on_success=Falsefor summary or preview buttons that should preserve the user's selection.- A selection-aware
extra_buttonsentry can render row selection controls even whenbulk_fields = []andbulk_delete = False. - Set
extra_button_selection_controls_disabled = Trueif 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.
permissionorpermission_checkhides or disables the button before selection-state checks run.permission_behaviordefaults 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 onlyextra_actionsinto aMoredropdown.
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_modeaffects only rowextra_actions, not top-of-pageextra_buttons.- In dropdown mode, the
Moretrigger uses the framework’sextra_defaultbutton styling unless you override the framework styles. extra_actions_dropdown_open_upward_bottom_rowscounts from the bottom of the currently rendered rows after filtering and pagination.- Set
extra_actions_dropdown_open_upward_bottom_rows = 0to keep every dropdown opening downward. modal_presentationis only used whendisplay_modal=True; it merges with the view presentation while this row action's modal is open.refresh_list_on_modal_closeis only used whendisplay_modal=True; preferHX-Trigger: {"refreshTable": true}when the endpoint knows it changed data.hidden_ifis an optional view method name with signature(obj, request) -> bool. ReturnTrueto omit the action for that row. Hidden actions are removed before disabled hooks are evaluated.- Set
hidden_if_mode = "lazy"only inextra_actions_mode = "dropdown"when the row relevance check is expensive and should be resolved when the rowMoremenu opens. Button-mode actions keep eager hidden-if evaluation. disabled_stateis a single-hook alternative todisabled_if/disabled_reason. Return a non-empty string to disable the action and show that string as the reason; returnNone,False, or an empty string to keep it enabled.- Set
disabled_state_mode = "lazy"only inextra_actions_mode = "dropdown"when the disabled reason is expensive to calculate and should be resolved when the rowMoremenu opens. Button-mode actions keep eager disabled-state evaluation. permissionorpermission_checkhides or disables the action beforehidden_ifanddisabled_staterun.permission_behaviordefaults to"hide".disabled_ifanddisabled_reasonare deprecated view method names used to disable a row action based on the current object and request. Usedisabled_stateinstead.- Do not combine
disabled_statewithdisabled_ifordisabled_reasonon the same action. - Use
hidden_ifwhen an action is not applicable for a row. Usedisabled_statewhen the action is applicable but unavailable and needs an explanatory reason. lock_sensitiveremains 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_onmust 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-dependencyendpoint 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
modelandbase_template_pathare required. - Auto-detection:
use_crispyauto-detects whethercrispy_formsis installed; everything else is opt-in. - Dependencies: Bulk operations require both
use_htmx = Trueanduse_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_fieldsandbulk_deleteconfigure the operation surface. Overridehas_power_bulk_update_permission(request)orhas_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 thefieldssetting. - Property shortcuts: Use
'__all__'for all properties,'__properties__'to reference thepropertiessetting.