Refactoring PowerCRUD Configuration
This is a plan to refactor configuration by consolidating all parameter resolution methods into a new ConfigMixin.config method, to make it easier to reason about and maintain configuration rules.
Background and Strategy
PowerCRUD already relies on an aggregator-mixin architecture: internal mixins, each with a narrow, well-defined responsibility, are combined into a single public PowerCRUDMixin. Downstream projects subclass one mixin plus Neapolitan’s CRUDView, and everything “just works” through shared self and MRO composition. This design keeps the surface area small for downstream use while retaining modularity for maintainers.
Configuration is the one area where the current pattern creates unnecessary cognitive load. Defaults and rule-based decisions are currently distributed across multiple mixin modules. To understand how a particular setting is determined, a maintainer must mentally traverse several mixins, locate the appropriate get_* methods, and simulate resolution through MRO. This increases maintenance difficulty and makes it harder to evolve PowerCRUD without unintended interactions.
CoreMixin currently mixes configuration attributes with operational behavior such as queryset sorting and list view rendering, so we are mandating the creation of a dedicated ConfigMixin. This mixin becomes the sole owner of configuration defaults, rule resolution, and user overrides while still participating in the aggregator so that downstream inheritance does not change.
ConfigMixin.config() will leverage the existing PowerCRUDMixinValidator from powercrud/validators.py to validate incoming attributes, normalize them, and expose a resolved configuration object (or namespace) that other mixins can consume. Relocating the validator-driven logic into one mixin ensures there is a single authoritative code path for every configuration decision.
Once this locus exists, all other mixins will be updated to read configuration exclusively through self.config() rather than through scattered get_* methods or ad-hoc attribute lookups. Behavioural mixins stop performing their own configuration decisions and instead treat config as a resolved, ready-to-use set of values. This shift reduces duplication, lowers the chance of contradictory logic between mixins, and simplifies the mental model for contributors.
AsyncManager remains separate because it is operational rather than behavioural; it is not tied to the view’s inheritance chain and should not participate in the configuration surface.
The overall effect is a cleaner, more predictable architecture:
- Convention over configuration for downstream users.
- Compositional mixins for maintainers.
- One coherent configuration module to eliminate MRO-based tracing and scattered defaults.
Plan
Scope
- Introduce a dedicated
ConfigMixinthat encapsulates all configuration defaults, rule evaluation, and validation (powered byPowerCRUDMixinValidator) without altering the externalPowerCRUDMixininheritance contract. - Migrate every behavioural mixin (
core,async,filtering,form,htmx,inline,paginate,table,url, andbulk) to read from the resolvedself.config()output instead of duplicating configuration decisions. - Preserve operational components like
AsyncManageroutside of the configuration locus while ensuring documentation/tests reflect the new API.
Risks
- Regression in default field/property resolution if the extraction to
ConfigMixinchanges evaluation order. - MRO or initialization conflicts if
ConfigMixinis inserted improperly relative to existing mixins. - Validator drift if new configuration attributes are added without updating
powercrud/validators.py.
Tasks
- Establish
ConfigMixinfoundation. 1.1. [X] Extract configuration attributes/resolution pipeline fromCoreMixinintoConfigMixin, wrapping the existingPowerCRUDMixinValidator. 1.2. [X] Exposeself.config()(or equivalent namespace) and ensure it is initialized before behavioural mixins rely on it. - Update mixins to consume centralized config.
2.1. [X] Update
core_mixin.pyto pull values fromself.config(). 2.2. [X] Updateasync_mixin.pyto pull values fromself.config(). 2.3. [X] Updatefiltering_mixin.pyto pull values fromself.config(). 2.4. [X] Updateform_mixin.pyto pull values fromself.config(). 2.5. [X] Updatehtmx_mixin.pyto pull values fromself.config(). 2.6. [X] Updateinline_editing_mixin.pyto pull values fromself.config(). 2.7. [X] Updatepaginate_mixin.pyto pull values fromself.config(). 2.8. [X] Updatetable_mixin.pyto pull values fromself.config(). 2.9. [X] Updateurl_mixin.pyto pull values fromself.config(). 2.10. [X] Update bulk-related mixins to pull values fromself.config(). 2.11. [X] Introduce shims/tests to confirm existing defaults and overrides behave identically. - Strengthen validation, docs, and release prep.
3.1. [X] Expand
powercrud/validators.pycoverage and tests to reflect any new config fields. 3.2. [X] Update documentation/changelog to describe the new configuration entry point and migration guidance.
Migration Notes
ConfigMixinis now the canonical place to declare configuration attributes and expose resolved values. Behavioural mixins should either overrideconfig()or, preferably, callresolve_config(self)to obtain the derived namespace (which provides helper flags such asuse_htmx_enabled, inline editing toggles, and table CSS metrics).PowerCRUDMixinValidatorhas been extended to cover the broader set of configuration knobs (bulk editing flags, dropdown sort hints, table classes, async-manager hooks, etc.) so overrides get validated consistently before reaching mixin logic. Updated unit tests intests/test_conf_logging_validators.pyensure the new restrictions are enforced.- Downstream projects that rely on legacy
get_*helpers can migrate incrementally: continue using existing mixins, but prefer reading from theconfignamespace (orresolve_config) instead of recomputing rules. This keeps the public API stable while allowing future releases to move more decisions intoConfigMixin.