* Implement Configuration Settings redesign with sticky header + tabs - Add allow_reordering parameter to AttributeForm to control reorder controls - Create ConfigEditFormHandler for unified multi-formset handling - Create ConfigEditResponseRenderer for page-based response generation - Add system_settings_redesigned.html template with sticky header + tabbed interface - Update ConfigSettingsView to use helper classes following Entity/Location patterns - Disable attribute reordering for system-defined config attributes - Maintain existing URL structure and form submission behavior * Fix AttributeEditContext integration with SubsystemAttributeEditData - Create SubsystemAttributeEditContext for proper template context - Add SubsystemAttributeEditData dataclass to cleanly pair formsets with contexts - Update form handler and response renderer to use dataclass approach - Simplify template logic by preparing data structure on server side - Remove complex template logic in favor of clean dataclass properties Fixes AttributeError: 'str' object has no attribute 'history_url_name' * Add missing URL patterns for AttributeEditContext integration - Add subsystem_attribute_history_inline and subsystem_attribute_restore_inline URL patterns - Create SubsystemAttributeHistoryInlineView and SubsystemAttributeRestoreInlineView - Follow Entity/Location pattern for inline history and restore functionality - Resolves NoReverseMatch error for subsystem_attribute_history_inline URL Fixes django.urls.exceptions.NoReverseMatch for inline attribute history URLs * Tweaks for getting backend structure in place. WIP * Config attrribute config mostly working, but still WIP. * Good checkpoint on config attribute editing. Works, but WIP. * Moved config settings to vertical tabs for subsystems. * Added selected settings tab restoration url strategy. * Added setting page error count badges to tabs. * Tweaks to config page entry point and labeling. * Added auto-dismiss settings update success message. * Major refactor of attr-v2-modal.js to remove global namespacing. * Fixed attr-v2 async initialization issue. * CONverting magic stricts to constants. * Refactor attribute javascript files to be better organized. * Fixed ENTER key submit suppression for attributes. Dead code removal. * Cleaned up all shared temp,ate id, class and selectors. * Refactor: Attribute editing javascript message posting. * Removed legacy config attribute history modal views. * Refactor for better attributeb editing response code organization. * Interim Refactor: Simple general attribute view working. WIP * Refactor to introduce attribute page vs. item editing contexts. * Have Entity and Location converted to refactored attribute editing. * Checkpoint on converting Subsystem to new attribute editing. WIP * Completed major attribute editing refactoring. * Working on unit tests for new attribute refactor. WIP * Fixed some unit tests. Tests are WIP though. * Miscellaneous cleanup tasks. * Fixed unit tests, linting and upload file deletion bug.
4.8 KiB
Attribute Editing Integration Guide
A comprehensive guide for integrating new models with the generic attribute editing system using the AttributeEditContext pattern.
Overview
The AttributeEditContext pattern provides a standardized way to implement attribute editing across different model types (Entity, Location, etc.) while maintaining ~95% code reuse through generic templates and handlers.
Benefits
- Code Reuse: Share 95% of template and handler logic across model types
- Consistency: Standardized UI/UX across all attribute editing interfaces
- Type Safety: Clean abstraction with type-safe owner-specific access
- Maintainability: Single source of truth for attribute editing functionality
- Extensibility: Easy to add new model types following established patterns
When to Use
Use this pattern when you have:
- A model that owns attributes (like Entity owns EntityAttribute)
- Need for modal-based attribute editing with file upload support
- Requirements for attribute history and restore functionality
- Desire for consistent editing UI across different model types
Prerequisites
Required Model Structure
Your implementation needs:
-
Owner Model: The main model (e.g.,
Entity,Location)class YourModel(models.Model): name = models.CharField(max_length=255) # other fields... -
Attribute Model: Related attribute model (e.g.,
EntityAttribute,LocationAttribute)class YourModelAttribute(models.Model): your_model = models.ForeignKey(YourModel, related_name='attributes') name = models.CharField(max_length=255) value = models.TextField() value_type_str = models.CharField(max_length=50) # history tracking fields... -
Template Directory Structure:
hi/apps/yourapp/templates/yourapp/ ├── modals/ │ └── yourmodel_edit.html └── panes/ └── yourmodel_edit_content_body.html
Step-by-Step Implementation
Step 1: Create AttributeItemEditContext Subclass
Create yourapp/yourmodel_attribute_edit_context.py:
See the following existing integrations:
# Single instance/formset
src/hi/apps/entity/entity_attribute_edit_context.py
src/hi/apps/location/location_attribute_edit_context.py
# Multipla instance/formset
src/hi/apps/config/subsystem_attribute_edit_context.py
Step 2: Create the needed views.
- Pick whether you need a single or multiple instance implementation
- Single instance view will include the mixin AttributeEditViewMixin
- Multiple instance views will include the mixin AttributeMultiEditViewMixin
- Your views get() method can render any sort of page or modal.
- The get() method must get its template comntext from the mixin
- The page or modal template must include a "content body" template (see below)
- The post always goes though a mixin method and returns custom JSON for front-end (attr.js)
The full set of views include:
- Main editing entry
- File upload handling (optional)
- Attribute History
- Atribute Value restore
Step 3: Create Content Body Template
- Create
yourapp/templates/yourapp/panes/yourmodel_edit_content_body.html: - This template must extend
attribute/components/edit_content_body.html - Override content blocks as needed.
Example:
src/hi/apps/config/templates/config/panes/subsystem_edit_content_body.html
src/hi/apps/entity/templates/entity/panes/entity_edit_content_body.html
src/hi/apps/location/templates/location/panes/location_edit_content_body.html
Step 4: Add URL Patterns
- Add URL patterns for the views.
- Follow the naming convenions in the attribute edit context classes or override them if needed
See:
src/hi/apps/entity/urls.py
src/hi/apps/location/urls.py
src/hi/apps/config/urls.py
Customizing Owner Fields
Override the owner_fields block to define model-specific fields:
{% block owner_fields %}
<div class="row">
<div class="col-md-8">
<!-- Name field -->
</div>
<div class="col-md-4">
<!-- Type or other field -->
</div>
</div>
{% endblock %}
Template Debugging
Add this to templates for debugging context variables:
{% comment %}DEBUG: Available context variables{% endcomment %}
{% if debug %}
<pre>{{ attr_context|pprint }}</pre>
<pre>Owner ID: {{ attr_context.owner_id }}</pre>
<pre>Owner Type: {{ attr_context.owner_type }}</pre>
{% endif %}
Context Variable Verification
Verify these key context variables are available:
attr_owner_context- The AttributeEditContext instanceattr_item_context- The AttributeEditContext instanceowner_form- Generic alias for model-specific formyour_model- Your specific model instancefile_attributes- QuerySet of file attributesregular_attributes_formset- Formset for non-file attributes