---
title: API Reference
description: Complete API reference for Django Admin module - all classes, methods, and utilities.
sidebar_label: API Reference
sidebar_position: 7
keywords:
  - django admin api
  - AdminConfig api
  - field types api
---

# API Reference

Complete reference for all Django Admin classes, methods, and utilities.

## Core Classes

### AdminConfig

Pydantic model for admin configuration.

```python
from django_cfg.modules.django_admin import AdminConfig

class AdminConfig(BaseModel):
    # Required
    model: Type[Model]

    # Display
    list_display: List[str] = []
    list_display_links: List[str] | None = None
    list_editable: List[str] = []       # Fields editable directly in list view
    list_per_page: int = 50
    list_max_show_all: int = 200

    # Display fields (auto-generate display methods)
    # Accepts List[FieldConfigType] — discriminated union of all 19 field types
    display_fields: List[FieldConfigType] = []

    # Filters and search
    # Accepts List[FilterSpec] where FilterSpec = str | type | tuple[str, type] | FilterConfig
    list_filter: List[FilterSpec] = []
    search_fields: List[str] = []
    date_hierarchy: str | None = None
    show_facets: bool = False  # Show result counts next to filter options (Django 5.0+)

    # Ordering
    ordering: List[str] = []

    # Readonly
    readonly_fields: List[str] = []

    # Form options
    autocomplete_fields: List[str] = []
    raw_id_fields: List[str] = []
    prepopulated_fields: Dict[str, Tuple[str, ...]] = {}

    # Performance
    select_related: List[str] = []
    prefetch_related: List[str] = []
    annotations: Dict[str, Any] = {}

    # Fieldsets
    fieldsets: List[FieldsetConfig] = []

    # Actions
    actions: List[ActionConfig] = []

    # Inlines
    inlines: List[Type] = []

    # Import/Export
    import_export_enabled: bool = False
    resource_class: Type | None = None

    # Other
    save_on_top: bool = False
    save_as: bool = False
    preserve_filters: bool = True
```

### PydanticAdmin

Base admin class that processes AdminConfig.

```python
from django_cfg.modules.django_admin.base import PydanticAdmin

@admin.register(MyModel)
class MyModelAdmin(PydanticAdmin):
    config = my_config

    # Access to HTML builder
    self.html.badge(...)
    self.html.span(...)
    # ... etc
```

**Properties:**
- `config: AdminConfig` - Configuration instance
- `html: HtmlBuilder` - HTML builder utility

## Field Types

### FieldConfig (Base)

Base class for all field configurations.

```python
class FieldConfig(BaseModel):
    name: str                    # Field name (required)
    title: str | None = None     # Display title
    ui_widget: str | None = None # Widget name
    empty_value: str = "—"       # Value when None
    ordering: str | None = None  # Sort field
    header: bool = False         # Sticky header column
```

### BadgeField

Badge with conditional colors.

```python
class BadgeField(FieldConfig):
    ui_widget: Literal["badge"] = "badge"
    variant: Literal["primary", "secondary", "success", "danger", "warning", "info"] = "primary"
    icon: str | None = None
    label_map: Dict[str, str] | None = None  # value → variant mapping
```

### BooleanField

Boolean indicator with icons.

```python
class BooleanField(FieldConfig):
    ui_widget: Literal["boolean"] = "boolean"
```

### AvatarField

User avatar with initials badge fallback.

**IMPORTANT:** The `name` parameter must be a **real model field**, not a virtual field or `@property`. Other fields like `name_field`, `initials_field`, `subtitle_field` can be properties or methods.

```python
class AvatarField(FieldConfig):
    ui_widget: Literal["avatar"] = "avatar"
    name: str                                # MUST be a real model field (e.g., "first_name", "username")
    photo_field: str                         # Model field for photo/avatar image
    name_field: str                          # Model field/property for display name
    initials_field: str                      # Field/property for extracting initials
    subtitle_field: str | None = None        # Optional subtitle (email, user_id) - can be property
    avatar_size: int = 40                    # Avatar size in pixels
    show_as_card: bool = False               # Show as user card layout
    variant_field: str | None = None         # Field to determine badge variant
    variant_map: dict[str, str] | None = None  # Map field values to badge variants
    default_variant: str = "secondary"       # Default badge variant
    initials_max_length: int = 2             # Maximum initials (1-3)
```

**Example:**
```python
# ✅ Correct - name is a real CharField
AvatarField(
    name="first_name",  # Real model field
    photo_field="photo_file",
    name_field="display_name",  # Can be @property
    initials_field="first_name",
)

# ❌ Wrong - name is a virtual field
AvatarField(
    name="user_avatar",  # Doesn't exist in model
    ...
)
```

### CurrencyField

Formatted currency.

```python
class CurrencyField(FieldConfig):
    ui_widget: Literal["currency"] = "currency"
    currency: str = "USD"  # Currency code
    precision: int = 2     # Decimal places
```

### DateTimeField

Formatted datetime.

```python
class DateTimeField(FieldConfig):
    ui_widget: Literal["datetime"] = "datetime"
    format: str = "%Y-%m-%d %H:%M"  # strftime format
    show_relative: bool = False      # Show "2 hours ago"
```

### TextField

Text with optional truncation.

```python
class TextField(FieldConfig):
    ui_widget: Literal["text"] = "text"
    max_length: int | None = None  # Truncate after N chars
    show_tooltip: bool = False     # Tooltip on hover
```

### UserField

User with avatar support.

```python
class UserField(FieldConfig):
    ui_widget: Literal["user_avatar"] = "user_avatar"
    # Inherits header=True for sticky column
```

### ShortUUIDField

Shortened UUID display with tooltip.

```python
class ShortUUIDField(FieldConfig):
    ui_widget: Literal["short_uuid"] = "short_uuid"
    length: int = 8                    # Number of characters to display
    copy_on_click: bool = True         # Enable click-to-copy
    show_full_on_hover: bool = True    # Show full UUID in tooltip
```

## Configuration Classes

### FieldsetConfig

Fieldset configuration.

```python
class FieldsetConfig(BaseModel):
    title: str                    # Fieldset title
    fields: List[str]             # Field names
    collapsed: bool = False       # Start collapsed
    description: str | None = None  # Optional description

    def to_django_fieldset(self) -> Tuple:
        """Convert to Django fieldset format."""
```

### ActionConfig

Action configuration for admin actions.

```python
class ActionConfig(BaseModel):
    name: str                              # Action name
    description: str                       # Display description
    action_type: Literal["bulk", "changelist"] = "bulk"  # Action type
    handler: Union[str, Callable]          # Action function or import path
    variant: str = "default"               # Button variant
    icon: Optional[str] = None             # Material icon name
    url_path: Optional[str] = None         # Custom URL path (changelist actions)
    confirmation: bool = False             # Show confirmation dialog
    permissions: List[str] = []            # Required permissions

    def get_handler_function(self) -> Callable:
        """Import and return the handler function."""
```

**Parameters:**

- **name** (str): Action function name
- **description** (str): Display text shown in UI
- **action_type** ("bulk" | "changelist"):
  - `"bulk"` - Traditional bulk action (requires selection, dropdown menu)
  - `"changelist"` - Button above listing (no selection required)
- **handler** (str | Callable): Action handler function or Python import path
- **variant** (str): Button color variant (default, success, warning, danger, primary, info)
- **icon** (str | None): Material Design icon name
- **url_path** (str | None): Custom URL path for changelist actions
- **confirmation** (bool): Show confirmation dialog before execution
- **permissions** (list[str]): Required permission codenames

**Handler Signatures:**
- Bulk: `handler(modeladmin, request, queryset) -> None`
- Changelist: `handler(modeladmin, request) -> HttpResponse`

## Decorators

### @computed_field

Decorator for custom display methods.

```python
from django_cfg.modules.django_admin import computed_field

@computed_field(
    short_description: str,         # Column header
    ordering: str | None = None,    # Sort field
    boolean: bool = False,          # Boolean display
    empty_value: str = "—"          # When None
)
def method_name(self, obj): ...
```

### @annotated_field

Decorator for annotated values.

```python
from django_cfg.modules.django_admin import annotated_field

@annotated_field(
    short_description: str,         # Column header
    annotation_name: str,           # Annotation key
    ordering: str | None = None,    # Sort field (defaults to annotation_name)
    empty_value: str = "—"          # When None
)
def method_name(self, obj): ...
```

## HTML Utilities

HTML utilities provide rich formatting for readonly fields and custom display methods in Django Admin.

### Using in Admin Classes

**The primary way to use HTML utilities is through `self.html.*` in admin methods:**

```python
from django_cfg.modules.django_admin.base import PydanticAdmin

class MyAdmin(PydanticAdmin):
    def my_readonly_field(self, obj):
        """Custom display using self.html utilities."""
        return self.html.inline([
            self.html.badge(obj.status, variant="success"),
            self.html.span(f"Items: {obj.count}", "font-semibold"),
        ])

    def another_display(self, obj):
        """Format numbers and UUIDs."""
        return self.html.inline([
            self.html.number(obj.price, precision=2, prefix="$"),
            self.html.uuid_short(obj.id, length=6),
        ])
```

All methods available on `self.html`:
- **Basic**: `icon()`, `span()`, `text()`, `div()`, `link()`, `empty()`
- **Code**: `code()`, `code_block()`
- **Badges**: `badge()`
- **Composition**: `inline()`, `stacked()`, `icon_text()`, `colored_text()`, `header()`
- **Formatting**: `number()`, `uuid_short()`, `truncate()`
- **Key-Value**: `key_value()`, `breakdown()`, `divider()`, `key_value_list()`
- **Progress**: `segment()`, `progress_bar()`
- **Markdown**: `markdown()`, `markdown_docs()`

### Module Structure (Advanced)

For advanced use cases outside admin classes, you can import modules directly:

```python
from django_cfg.modules.django_admin.utils import (
    BaseElements,           # Basic HTML: icon, span, text, div, link, empty
    CodeElements,          # Code blocks: code, code_block
    BadgeElements,         # Badges: badge
    CompositionElements,   # Composition: inline, icon_text, colored_text, header
    FormattingElements,    # Formatting: number, uuid_short
    KeyValueElements,      # Key-value: key_value, breakdown, divider
    ProgressElements,      # Progress: segment, progress_bar
    MarkdownIntegration,   # Markdown: markdown, markdown_docs
)
```

### BaseElements

Basic HTML building blocks.

#### icon()

```python
BaseElements.icon(
    icon_name: str,
    size: str = "xs",          # xs, sm, base, lg, xl
    css_class: str = ""
) -> SafeString
```

#### span()

```python
BaseElements.span(
    text: Any,
    css_class: str = ""
) -> SafeString
```

#### text()

Styled text with semantic variants.

```python
BaseElements.text(
    content: Any,
    variant: str | None = None,    # success, warning, danger, info, primary
    size: str | None = None,       # xs, sm, base, lg, xl, 2xl
    weight: str | None = None,     # normal, medium, semibold, bold
    muted: bool = False
) -> SafeString
```

#### div()

```python
BaseElements.div(
    content: Any,
    css_class: str = ""
) -> SafeString
```

#### link()

```python
BaseElements.link(
    url: str,
    text: str,
    css_class: str = "",
    target: str = ""           # _blank, _self, etc.
) -> SafeString
```

#### empty()

```python
BaseElements.empty(
    text: str = "—"
) -> SafeString
```

### CodeElements

Code display utilities.

#### code()

Inline code block.

```python
CodeElements.code(
    text: Any,
    css_class: str = ""
) -> SafeString
```

#### code_block()

Multi-line code block with syntax highlighting support.

```python
CodeElements.code_block(
    text: Any,
    language: str | None = None,    # json, python, bash, etc.
    max_height: str | None = None,  # "400px", "20rem"
    variant: str = "default"        # default, warning, danger, success, info
) -> SafeString
```

### BadgeElements

Badge rendering.

#### badge()

```python
BadgeElements.badge(
    text: Any,
    variant: str = "primary",  # primary, success, warning, danger, info, secondary
    icon: str | None = None    # Material icon name
) -> SafeString
```

### CompositionElements

Element composition utilities.

#### inline()

Join items with separator, preserving SafeString HTML.

```python
CompositionElements.inline(
    *items,
    separator: str = " | ",
    size: str = "small",       # small, medium, large
    css_class: str = ""
) -> SafeString
```

**Usage:**
```python
# Join multiple elements with separator
def stats_display(self, obj):
    return CompositionElements.inline(
        CompositionElements.icon_text(Icons.EDIT, obj.posts_count),
        CompositionElements.icon_text(Icons.CHAT, obj.comments_count),
        separator=" | "
    )
```

#### stacked()

Stack items vertically (one below another). Useful for multi-line display in computed fields.

```python
CompositionElements.stacked(
    items: list,
    css_class: str = ""
) -> SafeString
```

**Usage:**
```python
# Multi-line pricing display
def pricing_info(self, obj):
    return self.html.stacked([
        self.html.text(f"In: ${obj.input_price}", weight="semibold"),
        self.html.text(f"Out: ${obj.output_price}", muted=True),
    ])

# Status with details
def status_display(self, obj):
    return self.html.stacked([
        self.html.badge(obj.status, variant="success"),
        self.html.text(f"Updated: {obj.updated_at}", muted=True, size="xs"),
    ])
```

#### icon_text()

Icon with text and optional color.

```python
CompositionElements.icon_text(
    icon_or_text: str | Any,
    text: Any = None,
    icon_size: str = "xs",
    separator: str = " ",
    color: str = None  # success, warning, danger, info, secondary, primary
) -> SafeString
```

**Examples:**

```python
# Icon with text
self.html.icon_text(Icons.EDIT, 5)

# Icon with text and color
self.html.icon_text(Icons.CHECK_CIRCLE, "Yes", color="success")
self.html.icon_text(Icons.CANCEL, "No", color="secondary")

# Just text (no icon)
self.html.icon_text("Active")
```

#### colored_text()

Colored text without icon.

```python
CompositionElements.colored_text(
    text: Any,
    color: str = None  # success, warning, danger, info, secondary, primary
) -> SafeString
```

**Examples:**

```python
# Time ago with color based on freshness
if age < 120:
    self.html.colored_text("2 minutes ago", "success")
elif age < 300:
    self.html.colored_text("5 minutes ago", "warning")
else:
    self.html.colored_text("10 minutes ago", "danger")
```

**Available colors:**
- `success` - Green (positive states)
- `warning` - Yellow (attention needed)
- `danger` / `error` - Red (critical states)
- `info` - Blue (informational)
- `secondary` - Gray (neutral)
- `primary` - Indigo (brand color)

#### header()

Header with avatar, title, and subtitle.

```python
CompositionElements.header(
    title: str,
    subtitle: str | None = None,
    initials: str | None = None,
    avatar_variant: str = "primary"
) -> SafeString
```

### FormattingElements

Number and UUID formatting.

#### number()

Smart number formatting with precision handling.

```python
FormattingElements.number(
    value: Any,
    precision: int = 8,
    thousands_separator: bool = True,
    strip_zeros: bool = True,
    min_threshold: float | None = None,
    compact: bool = False,              # Use K/M/B/T suffixes
    prefix: str = "",
    suffix: str = "",
    css_class: str = ""
) -> SafeString
```

**Usage:**
```python
# Currency
FormattingElements.number(1234.56, precision=2, prefix="$")  # "$1,234.56"

# Compact notation
FormattingElements.number(1500000, compact=True, prefix="$")  # "$1.5M"

# Crypto balance
FormattingElements.number(0.00012345, precision=8)  # "0.00012345"
```

#### uuid_short()

Shorten UUID with tooltip.

```python
FormattingElements.uuid_short(
    uuid_value: Any,
    length: int = 6,           # Number of characters to show
    show_tooltip: bool = True  # Show full UUID on hover
) -> SafeString
```

#### truncate()

Truncate text to specified length with optional tooltip.

```python
FormattingElements.truncate(
    text: str,
    length: int = 100,         # Maximum length (default: 100)
    suffix: str = "...",       # Text to append when truncated
    show_tooltip: bool = True  # Show full text on hover (default: True)
) -> SafeString
```

**Usage:**
```python
# Truncate long message
self.html.truncate("Long message text here", length=50)

# Custom suffix
self.html.truncate(obj.description, length=80, suffix="…")

# No tooltip
self.html.truncate(obj.message_text, show_tooltip=False)
```

**Returns:**
- If text is shorter than limit: returns text as-is
- If text is longer: truncates and adds suffix
- With tooltip: shows full text on hover

### KeyValueElements

Key-value pair utilities.

#### key_value()

Single key-value pair.

```python
KeyValueElements.key_value(
    key: str,
    value: Any,
    icon: str | None = None,
    indent: bool = False,
    divider: bool = False,
    value_variant: str | None = None,
    value_size: str | None = None
) -> SafeString
```

#### breakdown()

Combine multiple key-value pairs.

```python
KeyValueElements.breakdown(*items) -> SafeString
```

#### divider()

```python
KeyValueElements.divider(css_class: str = "my-2") -> SafeString
```

### ProgressElements

Progress bar utilities.

#### segment()

Create progress bar segment.

```python
ProgressElements.segment(
    percentage: float,
    variant: str = 'primary',
    label: str = ''
) -> dict
```

#### progress_bar()

Multi-segment progress bar.

```python
ProgressElements.progress_bar(
    *segments,
    width: str = "w-full max-w-xs",
    height: str = "h-6",
    show_labels: bool = True,
    rounded: bool = True
) -> SafeString
```

**Usage:**
```python
ProgressElements.progress_bar(
    ProgressElements.segment(60, variant='success', label='Available'),
    ProgressElements.segment(40, variant='warning', label='Locked')
)
```

### MarkdownIntegration

Markdown rendering integration.

#### markdown()

Render markdown text.

```python
MarkdownIntegration.markdown(
    text: str,
    css_class: str = "",
    max_height: str | None = None,
    enable_plugins: bool = True
) -> SafeString
```

#### markdown_docs()

Render markdown documentation with collapsible UI.

```python
MarkdownIntegration.markdown_docs(
    content: str | Path,
    collapsible: bool = True,
    title: str = "Documentation",
    icon: str = "description",
    max_height: str | None = "500px",
    enable_plugins: bool = True,
    default_open: bool = False
) -> SafeString
```

## Display Utilities

### UserDisplay

```python
from django_cfg.modules.django_admin.utils.displays import UserDisplay
from django_cfg.modules.django_admin.models.display_models import UserDisplayConfig

# With avatar
UserDisplay.with_avatar(
    user: User,
    config: UserDisplayConfig | None = None
) -> List[str]  # [name, email, initials, avatar_data]

# Simple display
UserDisplay.simple(
    user: User,
    config: UserDisplayConfig | None = None
) -> SafeString
```

**UserDisplayConfig:**
```python
class UserDisplayConfig(BaseModel):
    show_avatar: bool = True
    show_email: bool = False
    avatar_size: str = "md"  # sm, md, lg
```

### MoneyDisplay

```python
from django_cfg.modules.django_admin.utils.displays import MoneyDisplay
from django_cfg.modules.django_admin.models.display_models import MoneyDisplayConfig

# Format amount
MoneyDisplay.amount(
    amount: Decimal | float | int,
    config: MoneyDisplayConfig | None = None
) -> SafeString
```

**MoneyDisplayConfig:**
```python
class MoneyDisplayConfig(BaseModel):
    currency: str = "USD"
    decimal_places: int = 2
    thousand_separator: bool = True
    show_currency_symbol: bool = True
    show_sign: bool = False
    smart_decimal_places: bool = False  # Auto-adjust based on amount
    rate_mode: bool = False             # Special formatting for rates
```

### DateTimeDisplay

```python
from django_cfg.modules.django_admin.utils.displays import DateTimeDisplay
from django_cfg.modules.django_admin.models.display_models import DateTimeDisplayConfig

# Relative time
DateTimeDisplay.relative(
    dt: datetime,
    config: DateTimeDisplayConfig | None = None
) -> SafeString

# Compact display
DateTimeDisplay.compact(
    dt: datetime,
    config: DateTimeDisplayConfig | None = None
) -> SafeString
```

**DateTimeDisplayConfig:**
```python
class DateTimeDisplayConfig(BaseModel):
    datetime_format: str = "%Y-%m-%d %H:%M"
    show_relative: bool = False
```

## Icons

### Icons Class

2234+ Material Design icons with autocomplete.

```python
from django_cfg.modules.django_admin import Icons

# Common icons
Icons.CHECK_CIRCLE
Icons.CANCEL
Icons.EDIT
Icons.DELETE
Icons.VISIBILITY
Icons.SETTINGS
Icons.PERSON
Icons.EMAIL
Icons.BUSINESS
Icons.SHOPPING_CART
Icons.RECEIPT
Icons.CURRENCY_BITCOIN
Icons.ADMIN_PANEL_SETTINGS
Icons.PRIORITY_HIGH
Icons.ARTICLE
Icons.CATEGORY
Icons.SCHEDULE
Icons.ERROR
Icons.WARNING
Icons.MOUSE
Icons.API
Icons.PACKAGE
Icons.HISTORY
Icons.SUPPORT_AGENT
Icons.SMART_TOY
Icons.CAMPAIGN
Icons.NEW_RELEASES
Icons.STAR
Icons.LOCAL_OFFER
Icons.ARROW_UPWARD
Icons.ARROW_DOWNWARD
Icons.REMOVE
Icons.SHOPPING_BAG

# ... 2200+ more icons with full IDE autocomplete
```

### IconCategories

Group icons by category for easier discovery.

```python
from django_cfg.modules.django_admin import IconCategories

IconCategories.ACTIONS      # Common action icons
IconCategories.CONTENT      # Content-related icons
IconCategories.COMMUNICATION  # Communication icons
IconCategories.SOCIAL       # Social icons
IconCategories.PLACES       # Location icons
IconCategories.DEVICE       # Device icons
```

## Widget Registry

Internal registry for widget renderers (advanced usage).

```python
from django_cfg.modules.django_admin import WidgetRegistry

# Register custom widget
WidgetRegistry.register("my_widget", my_render_function)

# Render widget
WidgetRegistry.render("badge", obj, field_name, config)
```

## Pydantic Models

### BadgeVariant

```python
from django_cfg.modules.django_admin import BadgeVariant

class BadgeVariant(str, Enum):
    PRIMARY = "primary"
    SECONDARY = "secondary"
    SUCCESS = "success"
    DANGER = "danger"
    WARNING = "warning"
    INFO = "info"
```

### BadgeConfig

```python
from django_cfg.modules.django_admin import BadgeConfig

class BadgeConfig(BaseModel):
    variant: BadgeVariant = BadgeVariant.PRIMARY
    icon: str | None = None
    css_classes: List[str] = []
```

### FlashFieldConfig

Pydantic model for declarative `one_time_flash_fields` entries.

```python
from django_cfg.modules.django_admin import FlashFieldConfig

class FlashFieldConfig(BaseModel):
    content_attr: str        # Model attribute to read as flash content
    title: str = ""          # Bold header text
    message: str = ""        # Subtitle/instruction text
    style: FlashStyle = "code_warning"  # One of 8 valid style keys
```

### FlashPayload

Pydantic model for session-stored flash data.

```python
from django_cfg.modules.django_admin import FlashPayload

class FlashPayload(BaseModel):
    content: Any
    title: str = ""
    message: str = ""
    style: FlashStyle = "code_warning"
```

### FlashStyle

Literal type for flash display style.

```python
from django_cfg.modules.django_admin import FlashStyle

FlashStyle = Literal[
    "code_warning",   # Code block with warning coloring
    "code_error",     # Code block with error coloring
    "code_success",   # Code block with success coloring
    "info",
    "warning",
    "error",
    "success",
    "raw",            # Raw HTML, no wrapper styling
]
```

### FieldConfigType

Discriminated union of all 19 field config types. Use for type narrowing in custom code.

```python
from django_cfg.modules.django_admin import FieldConfigType

# FieldConfigType is a Union of all concrete FieldConfig subclasses,
# discriminated on the `ui_widget` literal field.
# Use it as the type annotation for display_fields entries:
display_fields: List[FieldConfigType] = [
    BadgeField(name="status"),
    CurrencyField(name="price"),
    # ... any of the 19 field config types
]
```

### DjangoFieldsets

TypeAlias for Django's native fieldsets format.

```python
from django_cfg.modules.django_admin import DjangoFieldsets

DjangoFieldsets = tuple[tuple[str | None, dict[str, Any]], ...]

# Example value:
fieldsets: DjangoFieldsets = (
    (None, {"fields": ["name", "email"]}),
    ("Advanced", {"fields": ["api_key"], "classes": ["collapse"]}),
)
```

### FilterSpec

TypeAlias for `list_filter` entries. Accepts a plain string field name, a filter class,
a `(field_name, filter_class)` tuple, or a `FilterConfig` instance.

```python
from django_cfg.modules.django_admin import FilterSpec

FilterSpec = str | type | tuple[str, type] | FilterConfig
```

---

### FilterConfig

Pydantic model for declarative filter configuration. Converts to the Django-compatible
`list_filter` entry format under the hood.

```python
from django_cfg.modules.django_admin import FilterConfig

FilterConfig(
    field: str,                         # Model field name
    type: FilterType | None = None,     # One of 17 preset filter types
    filter_class: type | None = None,   # Raw Django/Unfold class (bypasses type)
    title: str | None = None,           # Sidebar label (SimpleListFilter types only)
)
```

**`type` must be set unless `filter_class` is provided.**

```python
from django_cfg.modules.django_admin import AdminConfig, FilterConfig

config = AdminConfig(
    model=Order,
    list_filter=[
        FilterConfig(field='status',     type='choices_dropdown'),
        FilterConfig(field='created_at', type='range_date'),
        FilterConfig(field='amount',     type='range_numeric'),
        FilterConfig(field='customer',   type='autocomplete'),
        FilterConfig(field='is_active',  type='boolean'),
        # Raw entries still work alongside FilterConfig:
        'currency',
        MyCustomFilter,
    ],
)
```

See **[Filters Guide](./filters)** for all type values and usage patterns.

---

### FilterType

`Literal` type with all valid `FilterConfig.type` values:

```python
FilterType = Literal[
    # FieldListFilter-based (bound to model field)
    "choices_dropdown",          # CharField/IntegerField with choices — single select
    "choices_dropdown_multiple", # Same — multi-select
    "choices_checkbox",          # choices as checkboxes
    "choices_radio",             # choices as radio buttons
    "boolean",                   # BooleanField — Yes/No
    "related_dropdown",          # ForeignKey — single select
    "related_dropdown_multiple", # ForeignKey — multi-select
    "related_checkbox",          # ForeignKey — checkboxes
    "autocomplete",              # ForeignKey with search input (needs related search_fields)
    "autocomplete_multiple",     # Same — multi-select
    "range_numeric",             # Numeric from/to inputs
    "slider",                    # Numeric slider (auto min/max from queryset)
    "range_date",                # DateField from/to
    "range_datetime",            # DateTimeField from/to
    "text",                      # icontains text search
    # SimpleListFilter-based (dynamic subclass — needs custom queryset logic)
    "dropdown",                  # Single dropdown
    "dropdown_multiple",         # Multi dropdown
]
```

## Flash / One-Time Secret Display

### FlashMixin

`FlashMixin` provides secure one-time display of sensitive values (API keys, passwords, tokens) in Django Admin readonly fields. Content is stored in the session, rendered once, then discarded.

#### flash_once()

Store a value for one-time display in a readonly field.

```python
FlashMixin.flash_once(
    request: HttpRequest,
    obj: Model,          # Must have pk set
    field_name: str,     # Name of the readonly field to inject into
    content: Any,        # Sensitive content to display
    title: str = "",     # Bold header text shown above content
    message: str = "",   # Subtitle/instruction text
    style: FlashStyle = "code_warning",
) -> None
```

**Parameters:**

- `request` — Django `HttpRequest`
- `obj` — Model instance; must have a `pk` (call after `save()`)
- `field_name` — str, name of the readonly field that will render the flash content
- `content` — Any, the sensitive value to display (string, dict, etc.)
- `title` — str, bold header text rendered above the content block
- `message` — str, subtitle or instruction shown below the title
- `style` — `FlashStyle`, controls the visual wrapper; one of 8 keys (`"code_warning"`, `"code_error"`, `"code_success"`, `"info"`, `"warning"`, `"error"`, `"success"`, `"raw"`)

**Example — call after object creation:**

```python
class MyModelAdmin(FlashMixin, PydanticAdmin):
    def save_model(self, request, obj, form, change):
        super().save_model(request, obj, form, change)
        if not change:  # only on creation
            self.flash_once(
                request, obj,
                field_name="api_key_display",
                content=obj.raw_api_key,
                title="API Key (shown once)",
                message="Copy and store it securely — it will not be shown again.",
                style="code_warning",
            )
```

#### one_time_flash_fields

Class attribute for declarative flash-on-create behaviour. After a new object is saved, `FlashMixin` automatically calls `flash_once()` for every entry.

```python
class MyModelAdmin(FlashMixin, PydanticAdmin):
    one_time_flash_fields: dict[str, FlashFieldConfig | dict] = {
        "api_key_display": FlashFieldConfig(
            content_attr="raw_api_key",
            title="API Key (shown once)",
            message="Store it securely — it will not be shown again.",
            style="code_warning",
        ),
    }
```

- **Type:** `dict[str, FlashFieldConfig | dict]`
- **Key:** readonly field name that renders the flash content
- **Value:** `FlashFieldConfig` instance (or equivalent plain `dict`)
- **Trigger:** fires automatically after object **creation** (not updates)

## Complete Import Example

```python
from django.contrib import admin
from django.db.models import Count

# Core
from django_cfg.modules.django_admin import (
    AdminConfig,
    FieldsetConfig,
    ActionConfig,
)

# Types and type aliases
from django_cfg.modules.django_admin import (
    FlashFieldConfig,    # Pydantic model for one_time_flash_fields entries
    FlashPayload,        # Pydantic model for session-stored flash data
    FlashStyle,          # Literal: "code_warning" | "code_error" | ... (8 values)
    FieldConfigType,     # Discriminated union of all 19 field config types
    DjangoFieldsets,     # TypeAlias: tuple[tuple[str | None, dict[str, Any]], ...]
    FilterSpec,          # TypeAlias: str | type | tuple[str, type] | FilterConfig
    FilterConfig,        # Pydantic model for declarative list_filter entries
    FilterType,          # Literal of all 17 filter type keys
)

# Field types
from django_cfg.modules.django_admin import (
    AvatarField,
    BadgeField,
    BooleanField,
    CurrencyField,
    DateTimeField,
    ShortUUIDField,
    TextField,
    UserField,
)

# Icons
from django_cfg.modules.django_admin import Icons

# Decorators
from django_cfg.modules.django_admin.utils import (
    computed_field,
    annotated_field,
    badge_field,
    currency_field,
)

# HTML utilities (new modular structure)
from django_cfg.modules.django_admin.utils import (
    BaseElements,           # Basic HTML elements
    CodeElements,          # Code blocks
    BadgeElements,         # Badges
    CompositionElements,   # Element composition
    FormattingElements,    # Number/UUID formatting
    KeyValueElements,      # Key-value pairs
    ProgressElements,      # Progress bars
    MarkdownIntegration,   # Markdown rendering
)

# Display utilities
from django_cfg.modules.django_admin.utils import (
    UserDisplay,
    MoneyDisplay,
    DateTimeDisplay,
    StatusBadge,
    ProgressBadge,
    CounterBadge,
    MarkdownRenderer,
)

# Display configs
from django_cfg.modules.django_admin.models.display_models import (
    UserDisplayConfig,
    MoneyDisplayConfig,
    DateTimeDisplayConfig,
)

# Badge configs
from django_cfg.modules.django_admin.models.badge_models import (
    StatusBadgeConfig,
    BadgeConfig,
)

# Base admin
from django_cfg.modules.django_admin.base import PydanticAdmin
```

## Version

Current version: **2.0.0**

## Next Steps

- **[Overview](./overview)** - Learn the philosophy
- **[Quick Start](./quick-start)** - Get started in 5 minutes
- **[Configuration](./configuration)** - Configuration guide
- **[Filters](./filters)** - Complete guide to filters
- **[Examples](./examples)** - Real-world examples
