Layout¶
Layout
¶
djadmin.layout.Layout
Top-level layout definition for a form.
Part of core djadmin. Can be used with or without djadmin-formset plugin.
Examples
Simple (works without plugin)¶
Layout( Field('name'), Field('email'), )
With fieldsets (works without plugin)¶
Layout( Fieldset('Personal', Field('name'), Field('birth_date'), ), )
With collections (⚠️ requires plugin!)¶
Layout( Field('name'), Collection('books', model=Book, fields=['title']), )
Method Resolution Order
djadmin.layout.Layout
Attributes
| Attribute | Value | Defined in |
|---|---|---|
__annotations__ |
{'items': <class 'tuple'>, 'renderer': type | None, 'css_... |
djadmin.layout.Layout
|
__dataclass_fields__ |
{'items': Field(name='items',type=<class 'tuple'>,default... |
djadmin.layout.Layout
|
__dataclass_params__ |
_DataclassParams(init=True,repr=True,eq=True,order=False,... |
djadmin.layout.Layout
|
__hash__ |
None |
djadmin.layout.Layout
|
__match_args__ |
('items', 'renderer', 'css_classes') |
djadmin.layout.Layout
|
renderer |
None |
djadmin.layout.Layout
|
Methods
__eq__(self, other)
Defined in:
<class 'djadmin.layout.Layout'>
Return self==value.
__init__(self, *items, renderer: type | None = None, css_classes: list[str] | None = None)
Defined in:
<class 'djadmin.layout.Layout'>
Initialize self. See help(type(self)) for accurate signature.
Source code
in layout.py
line 600
def __init__(self, *items, renderer: type | None = None, css_classes: list[str] | None = None):
self.items = items
self.renderer = renderer
self.css_classes = css_classes or []
if not items:
raise ValueError('Layout must contain at least one item')
__repr__(self)
Defined in:
<class 'djadmin.layout.Layout'>
Multi-line string representation for readability.
Source code
in layout.py
line 775
def __repr__(self):
"""Multi-line string representation for readability."""
if len(self.items) == 1:
# Single item - keep on one line
items_repr = repr(self.items[0])
else:
# Multiple items - multi-line with indentation
items_repr = ',\n '.join(repr(item) for item in self.items)
items_repr = f'\n {items_repr}\n'
parts = [items_repr]
if self.renderer:
if hasattr(self.renderer, '__name__'):
parts.append(f'renderer={self.renderer.__name__}')
else:
parts.append(f'renderer={self.renderer!r}')
if self.css_classes:
parts.append(f'css_classes={self.css_classes!r}')
return f"Layout({', '.join(parts)})"
from_fieldsets(fieldsets)
@classmethod
Defined in:
<class 'djadmin.layout.Layout'>
Convert Django admin fieldsets to Layout.
Converts the Django admin fieldsets format to the Layout API: - Named fieldsets → Fieldset with legend - Unnamed fieldsets (None, {...}) → Fieldset with legend=None - Tuple syntax ('field1', 'field2') → Row(Field('field1'), Field('field2')) - 'classes' → css_classes - 'description' → description
Args: fieldsets: Django admin fieldsets tuple format
Returns: Layout instance
Example: # Django admin format fieldsets = ( ('Personal', { 'fields': ('name', ('first_name', 'last_name')) }), )
# Converts to:
Layout(
Fieldset('Personal',
Field('name'),
Row(
Field('first_name'),
Field('last_name'),
),
),
)
Source code
in layout.py
line 608
@classmethod
def from_fieldsets(cls, fieldsets):
"""
Convert Django admin fieldsets to Layout.
Converts the Django admin fieldsets format to the Layout API:
- Named fieldsets → Fieldset with legend
- Unnamed fieldsets (None, {...}) → Fieldset with legend=None
- Tuple syntax ('field1', 'field2') → Row(Field('field1'), Field('field2'))
- 'classes' → css_classes
- 'description' → description
Args:
fieldsets: Django admin fieldsets tuple format
Returns:
Layout instance
Example:
# Django admin format
fieldsets = (
('Personal', {
'fields': ('name', ('first_name', 'last_name'))
}),
)
# Converts to:
Layout(
Fieldset('Personal',
Field('name'),
Row(
Field('first_name'),
Field('last_name'),
),
),
)
"""
layout_items = []
for fieldset_def in fieldsets:
# fieldset_def is (legend, options_dict)
legend, options = fieldset_def
# Get fields from options
fields_spec = options.get('fields', ())
description = options.get('description')
classes = options.get('classes', [])
# Convert fields spec to Field/Row objects
fieldset_items = []
for field_spec in fields_spec:
if isinstance(field_spec, tuple):
# Tuple means Row
row_fields = [Field(name) if isinstance(name, str) else name for name in field_spec]
fieldset_items.append(Row(*row_fields))
elif isinstance(field_spec, str):
# String means Field
fieldset_items.append(Field(field_spec))
elif isinstance(field_spec, Field):
# Already a Field object
fieldset_items.append(field_spec)
else:
raise ValueError(f'Unknown field spec type: {type(field_spec)}')
# Create Fieldset
fieldset = Fieldset(legend, *fieldset_items, description=description, css_classes=classes)
layout_items.append(fieldset)
return cls(*layout_items)
get_features(self) -> set
Defined in:
<class 'djadmin.layout.Layout'>
Get the set of features required by this layout.
Used for feature advertising to plugins.
Returns: Set of feature names: - 'collections' / 'inlines': Layout contains Collection components - 'conditional_fields': Layout uses show_if/hide_if - 'computed_fields': Layout uses calculate
Source code
in layout.py
line 678
def get_features(self) -> set:
"""
Get the set of features required by this layout.
Used for feature advertising to plugins.
Returns:
Set of feature names:
- 'collections' / 'inlines': Layout contains Collection components
- 'conditional_fields': Layout uses show_if/hide_if
- 'computed_fields': Layout uses calculate
"""
features = set()
def check_item(item):
if isinstance(item, Collection):
features.add('collections')
features.add('inlines') # Alias
# Recursively check nested layout
if item.layout:
features.update(item.layout.get_features())
elif isinstance(item, Field):
if item.show_if or item.hide_if:
features.add('conditional_fields')
if item.calculate:
features.add('computed_fields')
elif isinstance(item, Fieldset | Row):
for field in item.fields:
check_item(field)
elif isinstance(item, Layout):
for i in item.items:
check_item(i)
for item in self.items:
check_item(item)
return features
get_field_names(self) -> list[str]
Defined in:
<class 'djadmin.layout.Layout'>
Recursively extract all field names from layout.
Used to provide Django's ModelForm with the fields list when only a layout is specified (no explicit fields attribute).
Returns: List of field names (strings) for use with Django's ModelForm fields attribute. Collections are excluded as they represent inline editing, not top-level fields.
Example: >>> layout = Layout( ... Field('name'), ... Fieldset('Details', ... Field('price'), ... Row(Field('sku'), Field('category')), ... ), ... ) >>> layout.get_field_names() ['name', 'price', 'sku', 'category']
Source code
in layout.py
line 719
def get_field_names(self) -> list[str]:
"""
Recursively extract all field names from layout.
Used to provide Django's ModelForm with the fields list when only
a layout is specified (no explicit fields attribute).
Returns:
List of field names (strings) for use with Django's ModelForm fields attribute.
Collections are excluded as they represent inline editing, not top-level fields.
Example:
>>> layout = Layout(
... Field('name'),
... Fieldset('Details',
... Field('price'),
... Row(Field('sku'), Field('category')),
... ),
... )
>>> layout.get_field_names()
['name', 'price', 'sku', 'category']
"""
def _extract_from_items(items):
"""Recursively extract field names from a collection of items."""
field_names = []
for item in items:
if isinstance(item, Field):
field_names.append(item.name)
elif isinstance(item, Fieldset | Row):
field_names.extend(_extract_from_items(item.fields))
elif isinstance(item, Collection):
# Collections are inlines, not top-level fields
pass
elif isinstance(item, Layout):
field_names.extend(_extract_from_items(item.items))
return field_names
return _extract_from_items(self.items)
render_for_display(self, obj) -> list
Defined in:
<class 'djadmin.layout.Layout'>
Render layout for display (top-level).
Args: obj: Model instance to get field values from
Returns: List of rendered layout items (each is a dict)
Source code
in layout.py
line 759
def render_for_display(self, obj) -> list:
"""
Render layout for display (top-level).
Args:
obj: Model instance to get field values from
Returns:
List of rendered layout items (each is a dict)
"""
items = []
for item in self.items:
items.append(item.render_for_display(obj))
return items
Fields
| Field | Type | Related To |
|---|---|---|
__dict__ |
getset_descriptor |
- |
__weakref__ |
getset_descriptor |
- |