Refactor form rendering components & add docstrings

This commit is contained in:
Jeremy Stretch
2024-03-15 12:59:42 -04:00
parent 2aaa552067
commit 3b28e8e615
7 changed files with 54 additions and 36 deletions

View File

@@ -3,28 +3,39 @@ import string
from functools import cached_property
__all__ = (
'FieldSet',
'InlineFields',
'ObjectAttribute',
'TabbedFieldGroups',
'TabbedGroups',
)
class FieldGroup:
class FieldSet:
"""
A generic grouping of fields, with an optional name. Each field will be rendered
on its own row under the heading (name).
"""
def __init__(self, *fields, name=None):
self.fields = fields
self.name = name
def __init__(self, label, *field_names):
self.field_names = field_names
class InlineFields:
"""
A set of fields rendered inline (side-by-side) with a shared label; typically nested within a FieldSet.
"""
def __init__(self, *fields, label=None):
self.fields = fields
self.label = label
class InlineFields(FieldGroup):
pass
class TabbedFieldGroups:
class TabbedGroups:
"""
Two or more groups of fields (FieldSets) arranged under tabs among which the user can navigate.
"""
def __init__(self, *groups):
self.groups = [
FieldGroup(*group) for group in groups
FieldSet(*group, name=name) for name, *group in groups
]
# Initialize a random ID for the group (for tab selection)
@@ -37,13 +48,15 @@ class TabbedFieldGroups:
return [
{
'id': f'{self.id}_{i}',
'title': group.label,
'fields': group.field_names,
'title': group.name,
'fields': group.fields,
} for i, group in enumerate(self.groups, start=1)
]
class ObjectAttribute:
"""
Renders the value for a specific attribute on the form's instance.
"""
def __init__(self, name):
self.name = name

View File

@@ -1,6 +1,6 @@
from django import template
from utilities.forms.rendering import InlineFields, ObjectAttribute, TabbedFieldGroups
from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups
__all__ = (
'getfield',
@@ -48,24 +48,29 @@ def widget_type(field):
#
@register.inclusion_tag('form_helpers/render_fieldset.html')
def render_fieldset(form, fieldset, heading=None):
def render_fieldset(form, fieldset):
"""
Render a group set of fields.
"""
# Handle legacy tuple-based fieldset definitions, e.g. (_('Label'), ('field1, 'field2', 'field3'))
if type(fieldset) is not FieldSet:
name, fields = fieldset
fieldset = FieldSet(*fields, name=name)
rows = []
for item in fieldset:
for item in fieldset.fields:
# Multiple fields side-by-side
if type(item) is InlineFields:
fields = [
form[name] for name in item.field_names if name in form.fields
form[name] for name in item.fields if name in form.fields
]
rows.append(
('inline', item.label, fields)
)
# Tabbed groups of fields
elif type(item) is TabbedFieldGroups:
elif type(item) is TabbedGroups:
tabs = [
{
'id': tab['id'],
@@ -95,7 +100,7 @@ def render_fieldset(form, fieldset, heading=None):
)
return {
'heading': heading,
'heading': fieldset.name,
'rows': rows,
}