Table Widgets#
Tables#
- class StaticTableRowWidget(cells: list[str | wildewidgets.widgets.base.Block], cell_tag: str | None = None, cell_css_class: str | None = None, **kwargs)[source]#
Bases:
BlockSimple static table row widget. This widget is used to create a row in a
StaticTableWidget.- Parameters:
cells – the cells to add to the row
cell_tag – the HTML tag for the cells
cell_css_class – the CSS class for the cells
**kwargs – additional keyword arguments to pass to the block
- class StaticTableWidget(headings: list[str | wildewidgets.widgets.base.Block] | None = None, rows: list[list[str | wildewidgets.widgets.base.Block]] | None = None, cell_css_class: str | None = None, **kwargs)[source]#
Bases:
BlockSimple static table widget. This differs from the
DataTabletype widgets in that it does not use dataTables.js and is therefore simpler for small lists of data.It offers a sorting mechanism by clicking on the “Sort” button in the heading of the column. The table is sorted by the text content of the cells in the column that the button is in. If every cell in that column is numeric (optional minus, digits, optional decimal), the column is sorted numerically; otherwise locale-aware alphabetical sort is used. Empty cells in numeric columns sort last (ascending) or first (descending).
Examples
With constructor arguments:
from wildewidgets import StaticTableWidget table = StaticTableWidget( headings=["Name", "Age", "City"], rows=[["John", 25, "New York"], ["Jane", 30, "Los Angeles"]] ) print(table)
With constructor overrides:
from wildewidgets import StaticTableWidget class MyStaticTableWidget(StaticTableWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_heading("Name") self.add_heading("Age") self.add_heading("City") self.add_row(["John", 25, "New York"]) self.add_row(["Jane", 30, "Los Angeles"]) table = MyStaticTableWidget() print(table)
With method calls:
from wildewidgets import StaticTableWidget table = StaticTableWidget() table.add_heading("Name") table.add_heading("Age") table.add_heading("City") table.add_row(["John", 25, "New York"]) table.add_row(["Jane", 30, "Los Angeles"]) print(table)
from wildewidgets import StaticTableWidget table = StaticTableWidget( headings=["Name", "Age", "City"], rows=[["John", 25, "New York"], ["Jane", 30, "Los Angeles"]] ) table.add_heading("Country") table.add_heading("Occupation") table.add_heading("City"sjj table.add_row( ["John", 25, "New York", "United States", "Software Engineer"] ) table.add_row( ["Jane", 30, "Los Angeles", "United States", "Software Engineer"] ) print(table)
- Keyword Arguments:
headings – the headings for the table
rows – the rows for the table
cell_css_class – the CSS class for the cells
**kwargs – additional keyword arguments to pass to the block
- add_heading(heading: str | wildewidgets.widgets.base.Block) None[source]#
Add a single heading to the table. Do this before adding any rows.
- Parameters:
heading – the heading to add to the table
- add_row(row: list[str | wildewidgets.widgets.base.Block]) None[source]#
Add a single row to the table. Do this after adding headings.
- property script: str#
A JavaScript script to sort the table by clicking on a button in the headings.
Iniitially, the table is sorted in the order they are listed in the data source.
It draws a button in the
<th>elements named “Sort” with the current sort order represented by an arrow (if we are sorting) or a blank (if we are not sorting). When the button is clicked, the table is sorted by the opposite of the current sort order or ascending (if no sort order is set), and the button text is updated to the opposite of the selected sort order.Note
The table is sorted by the text content of the cells in the column that the button is in. If every cell in that column is numeric (optional minus, digits, optional decimal), the column is sorted numerically; otherwise locale-aware alphabetical sort is used. Empty cells in numeric columns sort last (ascending) or first (descending).
- Parameters:
self – the widget instance
- Returns:
A string of JavaScript code to sort the table by clicking on the headings.
- class ActionButtonModelTable(*args, actions: list[wildewidgets.widgets.tables.actions.RowActionButton] | None = None, button_size: str | None = None, justify: Optional[Literal['start', 'center', 'end']] = None, **kwargs)[source]#
Bases:
ActionButtonBlockMixin,ModelTableMixin,BaseDataTableModel table with customizable row action buttons.
This class allows you to define action buttons for each row using
RowActionButtoninstances and subclasses, providing flexibility in button appearance and behavior. Buttons can perform different actions based on the row data, like linking to detail pages, opening modals, or submitting forms.Example
from django.db import models from wildewidgets import ( ActionButtonModelTable, RowModelUrlButton, RowFormButton ) class Author(models.Model): full_name = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=200) authors = models.ManyToManyField(Author, related_name='books') isbn = models.CharField(max_length=20) def get_absolute_url(self): return f"/books/{self.id}/" def get_delete_url(self): return f"/books/{self.id}/delete/" class BookTable(ActionButtonModelTable): model = Book fields = ['title', 'authors__full_name', 'isbn'] verbose_names = {'authors__full_name': 'Authors'} actions = [ RowModelUrlButton( text='View', color='primary', attribute='get_absolute_url' ), RowFormButton( text='Delete', color='danger', attribute='get_delete_url', form_fields=['id'], confirm_text='Are you sure you want to delete this book?' ) ]
- class BasicModelTable(*args, model: type[django.db.models.base.Model] | None = None, fields: str | list[str] | None = None, hidden: list[str] | None = None, verbose_names: dict[str, str] | None = None, unsortable: list[str] | None = None, unsearchable: list[str] | None = None, field_types: dict[str, str] | None = None, alignment: dict[str, Literal['left', 'right', 'center']] | None = None, bool_icons: dict[str, tuple[tuple[str, str], ...]] | None = None, **kwargs)[source]#
Bases:
ModelTableMixin,DataTableReady-to-use table for displaying Django model data.
This class combines
ModelTableMixinandDataTableto provide a complete solution for displaying model data with minimal configuration. Simply define your model and field configuration as class attributes.Example
from django.db import models from wildewidgets.widgets.tables import BasicModelTable class Author(models.Model): full_name = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=200) authors = models.ManyToManyField(Author, related_name='books') isbn = models.CharField(max_length=20) # Example table using BasicModelTable class BookTable(BasicModelTable): model = Book fields = ['title', 'authors__full_name', 'isbn'] alignment = {'authors': 'left'} verbose_names = {'authors__full_name': 'Authors'} buttons = True striped = True def render_authors__full_name_column(self, row, column): authors = row.authors.all() if authors.count() > 1: return f"{authors[0].full_name} + {authors.count()-1} more" return authors[0].full_name if authors else ""
- class DataTable(*args, actions: Any = None, action_button_size: str | None = None, default_action_button_label: str | None = None, default_action_button_color_class: str | None = None, **kwargs)[source]#
Bases:
ActionsButtonsBySpecMixin,BaseDataTableStandard data table implementation with action buttons specs.
This class combines
BaseDataTablewithwildewidgets.ActionsButtonsBySpecMixinto create a complete table implementation that supports all base table features plus action buttons for each row.Example
from wildewidgets.widgets.tables import DataTable class MyTable(DataTable): actions = [ ('Edit', 'my_app:edit'), ('Delete', 'my_app:delete', 'post', 'danger') ] def get_queryset(self): return MyModel.objects.all()
- class LookupModelTable(*args, **kwargs)[source]#
Bases:
ActionButtonBlockMixin,ModelTableMixin,BaseDataTableSpecialized table for lookup/reference data with automatic field discovery. This is used by the
wildewidgets.ModelViewSetto display reference data like categories, statuses, or other lookup tables.This table is designed for displaying reference/lookup tables and automatically configures itself to:
Show only direct model fields (no related fields)
Left-align the ID column for better readability
Support row actions via
wildewidgets.ActionButtonBlockMixin
This table is ideal for admin interfaces or data management views for reference data like categories, statuses, or other lookup tables.
- Requirements:
Your model must implement
get_absolute_url,get_update_urlandget_delete_urlmethods
Note
If fields are not specified, the table automatically includes all non-relation fields from the model.
Example
from django.db import models from wildewidgets.widgets.tables import LookupModelTable class Category(models.Model): name = models.CharField(max_length=100) description = models.TextField(blank=True, null=True) def get_absolute_url(self): return f"/categories/{self.id}/" def get_update_url(self): return f"/categories/{self.id}/edit/" def get_delete_url(self): return f"/categories/{self.id}/delete/" class CategoryTable(LookupModelTable): model = Category
- Keyword Arguments:
fields – A list of field names to include in the table. If not provided, defaults to all non-relation fields on the model.
model – The Django model class to use for this table. If not provided, the
modelattribute must be set on the class.
- Raises:
ImproperlyConfigured – If the model is not set as either a class attribute or provided during initialization.
- actions: list[RowActionButton] = []#
A list of
RowActionButtonsubclasses to display in the “Actions” column.
- class ModelTableMixin(*args, model: type[django.db.models.base.Model] | None = None, fields: str | list[str] | None = None, hidden: list[str] | None = None, verbose_names: dict[str, str] | None = None, unsortable: list[str] | None = None, unsearchable: list[str] | None = None, field_types: dict[str, str] | None = None, alignment: dict[str, Literal['left', 'right', 'center']] | None = None, bool_icons: dict[str, tuple[tuple[str, str], ...]] | None = None, **kwargs)[source]#
Bases:
objectMixin used to create a table from a Django Model with automatic column configuration.
This mixin automatically discovers model fields and creates appropriate table columns with sensible defaults for alignment, sorting, and display formatting. It handles both direct model fields and related fields through Django’s double-underscore notation.
Important
Typically you will not use this directly in your code, but instead use one of the pre-defined table classes like
BasicModelTable,ActionButtonModelTable, orStandardActionButtonModelTable.Notes
Django
DateFieldandDateTimeFieldfields are automatically formatted using theWILDEWIDGETS_DATE_FORMATand `` WILDEWIDGETS_DATETIME_FORMAT`` settings.Django
BooleanFieldfields can be rendered with custom icons using thebool_iconsattribute, which maps field names to tuples of icon specifications.For the
field_typesattribute/kwarg, currently available choices for the dict values are:date: For formatting date fieldsdatetime: For formatting datetime fieldscurrency: For formatting currency values with a dollar signbool: For rendering boolean values as check icons
You may add a new field type by implementing a method named
render_FIELD_type_columnon your table class, whereFIELDis the name of the field type (e.g.,render_currency_type_column)
Example
from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey from wildewidgets.widgets.tables import ModelTableMixin, DataTable class Author(models.Model): full_name = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=200) authors = models.ManyToManyField(Author, related_name='books') isbn = models.CharField(max_length=20) published_date = models.DateField() # Example table using ModelTableMixin class BookTable(ModelTableMixin, DataTable): model = Book fields = ['title', 'authors__full_name', 'isbn', 'published_date'] alignment = {'isbn': 'center', 'published_date': 'right'} verbose_names = {'authors__full_name': 'Authors'} field_types = {'published_date': 'date'} def render_authors__full_name_column(self, row, column): return ", ".join([a.full_name for a in row.authors.all()])
- Parameters:
*args – Variable length argument list (unused)
- Keyword Arguments:
model – The Django model class to use for this table. If not provided, the
modelattribute must be set on the class.fields – A list of field names to include in the table. If not provided, defaults to all fields on the model. The
fieldsattribute can be set toNone, an empty list, or the string “__all__” to include all fields on the model. If a list is provided, it can include related fields using Django’s double-underscore notation (e.g., authors__full_name).hidden – A list of field names to hide by default. Users can unhide fields via the table controls.
verbose_names – A dictionary mapping field names to custom column headers where the key is the field name and the value is the desired header text.
unsortable – A list of field names that will not be sortable. This means that the up/down arrows will not be displayed in the table header for these fields, and they will not be included in the sort query.
unsearchable – A list of field names that will not be searched when doing a global table search. This means the field will not be included in the search query, but it will still be displayed in the table.
field_types – A dictionary mapping field names to data types for automatic formatting of table values.
alignment – A dictionary mapping field names to alignment values. Valid values are
left,right, andcenter. The key is the field name and the value is the alignment value. If not provided, defaults toleftfor all text fields andrightfor numeric fields.bool_icons – A dictionary mapping field names to tuples of icon specifications for rendering boolean values. Each tuple should contain 1-2 icon specs: (icon_name, css_class) for True and optionally (icon_name, css_class) for False.
- Raises:
ImproperlyConfigured – If the model is not set and no model is provided during initialization.
django.core.exceptions.FieldDoesNotExist – If a specified field does not exist on the model or related models.
- get_field(field_name: str) models.Field | models.ForeignObjectRel | GenericForeignKey | None[source]#
Get a field instance by name, checking both direct and related fields.
- Parameters:
field_name – The name of the field to retrieve
- Returns:
The Django Field instance or None if not found
Resolve a field from a related model using Django’s double-underscore notation.
This method handles field paths like ‘author__publisher__name’ by traversing the model relationships to find the final field object.
- Parameters:
current_model – The starting model class
name – Field path using Django’s double-underscore notation
- Returns:
The Django Field instance for the final field in the path, or None if not found
Example
For a path ‘author__publisher__name’, this would:
Get the ‘author’ field from the current model
Get the related model (Publisher)
Return the ‘name’ field from the Publisher model
Get the related model for a relationship field.
- Parameters:
current_model – The model containing the relationship field
field_name – The name of the relationship field
- Returns:
The related model class or None if not found
- load_all_fields() None[source]#
Add columns for all discovered model fields to the table.
This is called when fields=”__all__” or when fields is empty.
- load_field(field_name: str) None[source]#
Add a column for a single field to the table.
This method handles field discovery, verbose name resolution, and column attribute configuration before adding the column to the table.
- Parameters:
field_name – The name of the field to add as a column
- render_bool_icon_column(value: Any, icon_data: tuple[tuple[str, str], ...]) str[source]#
Format a boolean value using custom icons.
- Parameters:
value – The boolean value to format
icon_data – Tuple of icon specifications (icon_name, css_class)
- Returns:
HTML for the specified icon based on the boolean value
Note
The icon_data tuple should contain 1-2 icon specifications: - First icon is used for True values - Second icon (if provided) is used for False values
- render_bool_type_column(value: Any) str[source]#
Format a boolean value as a check icon for True values.
- Parameters:
value – The boolean value to format
- Returns:
HTML for a checkmark icon if True, empty string if False
- render_column(row: Any, column: str) str[source]#
Render a cell value with appropriate formatting based on field type.
This method handles special formatting for different field types:
Applies custom rendering for fields in field_types dictionary
Automatically formats DateTimeField and DateField values
Applies icon rendering for boolean fields in bool_icons dictionary
- Parameters:
row – The data object for the current row
column – The name of the column to render
- Returns:
Formatted HTML string for the cell value
- render_currency_type_column(value: Any) str[source]#
Format a value as currency with a dollar sign.
- Parameters:
value – The value to format
- Returns:
Formatted currency string with dollar sign
- render_date_type_column(value: datetime.date) str[source]#
Format a date value with the configured date format.
- Parameters:
value – The date value to format
- Returns:
Formatted date string, optionally with title attribute for full date format
Note
The format can be customized using the WILDEWIDGETS_DATE_FORMAT setting in Django settings.
- render_datetime_type_column(value: datetime.datetime) str[source]#
Format a datetime value with the configured datetime format.
- Parameters:
value – The datetime value to format
- Returns:
Formatted datetime string
Note
The format can be customized using the WILDEWIDGETS_DATETIME_FORMAT setting in Django settings.
- set_standard_column_attributes(field_name: str, kwargs: dict[str, Any]) None[source]#
Set standard column attributes based on field type and configuration.
This method configures:
Visibility based on the ‘hidden’ list
Searchability based on the ‘unsearchable’ list
Sortability based on the ‘unsortable’ list
Alignment based on the ‘alignment’ dict or field type
- Parameters:
field_name – The name of the field to configure
kwargs – Dictionary of attributes to update
- alignment: dict[str, Literal['left', 'right', 'center']] = {}#
A mapping of field name to field alignment. Valid values are
left,right, and :center
- field_types: dict[str, str] = {}#
A mapping of field name to data type. This is used to do some automatic formatting of table values.
- fields: str | list[str] | None = []#
This is either
None, the string__all__or a list of column names to use in our table. For the list, entries can either be field names from ourmodel, or names of computed fields that will be rendered with arender_FIELD_columnmethod. IfNone, empty list or__all__, display all fields on themodel.
The list of field names to hide by default
- model_fields: dict[str, models.Field | models.ForeignObjectRel | GenericForeignKey]#
A mapping of field name to Django field class
A mapping of field name to Django related field class
- class StandardActionButtonModelTable(*args, actions: list[wildewidgets.widgets.tables.actions.RowActionButton] | None = None, button_size: str | None = None, justify: Optional[Literal['start', 'center', 'end']] = None, **kwargs)[source]#
Bases:
ActionButtonBlockMixin,ModelTableMixin,BaseDataTableModel table with standard “Edit” and “Delete” buttons for each row.
This class provides a convenient implementation for the common pattern of displaying model data with “Edit” and “Delete” actions. It automatically creates these buttons and links them to the appropriate URLs from your model.
- Requirements:
Your model must have the
wildewidgets.ViewSetMixinmixin in its inheritance chainYour model must implement
get_absolute_url,get_update_urlandget_delete_urlmethods
- model#
The Django model class to display
- fields#
List of fields to include in the table
Example
from django.db import models from django.urls import reverse from wildewidgets.models import ViewSetMixin class Book(ViewSetMixin, models.Model): title = models.CharField('Title', max_length=100) isbn = models.CharField('ISBN', max_length=20) def get_absolute_url(self): return reverse('books:detail', args=[self.id]) def get_update_url(self): return reverse('books:edit', args=[self.id]) def get_delete_url(self): return reverse('books:delete', args=[self.id]) class BookTable(StandardActionButtonModelTable): model = Book fields = ['title', 'isbn']
- class WidgetCellMixin[source]#
Bases:
objectMixin that enables using custom widgets to render individual table cells.
This mixin allows you to specify custom widget classes for different columns, providing complete control over how cell data is rendered. Each widget receives the row data and column name, allowing for complex rendering based on the full context of the data.
If a widget is defined for a column in the
cell_widgetsdictionary, it will be used to render the cell. Otherwise, the standard column rendering will be used.Important
Cell widgets need to be
wildewidgets.Blocksubclasses that accept two additional keyword arguments:row: The data object for the current row
column: The name of the column to render
from wildewidgets import Block class MyCellWidget(Block): def __init__(self, row=None, column=None, **kwargs): self.row = row self.column = column self.value = getattr(row, column) super().__init__(f"Value is {self.value}", **kwargs)
- cell_widgets#
Dictionary mapping column names to widget classes for rendering cells in those columns
Example
from wildewidgets import WidgetCellMixin, DataTable from wildewidgets.widgets.base import Block class StatusWidget(Block): def __init__(self, row=None, column=None, **kwargs): super().__init__(**kwargs) status = getattr(row, column) if status == 'active': self.add_class('badge bg-success') elif status == 'pending': self.add_class('badge bg-warning') else: self.add_class('badge bg-secondary') self.text = status.capitalize() class MyTable(WidgetCellMixin, DataTable): cell_widgets = { 'status': StatusWidget }
- render_column(row: Any, column: str) str[source]#
Render a cell using a custom widget if defined for the column.
If a widget is defined for the column in
cell_widgets, this method instantiates the widget with the row and column data and returns its rendered output. Otherwise, it falls back to the standard column rendering.- Parameters:
row – The data object for the current row
column – The name of the column to render
- Returns:
Rendered HTML string for the cell
Components#
- class DataTableColumn(field: str, verbose_name: str | None = None, searchable: bool = False, sortable: bool = False, align: str = 'left', head_align: str = 'left', visible: bool = True, wrap: bool = True)[source]#
Bases:
objectDefines a column configuration for a
wildewidgets.DataTable.This class stores the configuration for a single column in a
DataTable, including display options, behavior, and formatting settings.Example
from wildewidgets import DataTableColumn # Create a right-aligned numeric column that can be sorted column = DataTableColumn( field="amount", verbose_name="Amount ($)", searchable=True, sortable=True, align="right" )
- Parameters:
field – Field name or identifier for the column
- Keyword Arguments:
verbose_name – Human-readable name for the column header (defaults to capitalized field name)
searchable – Whether this column is included in global searches
sortable – Whether the table can be sorted by this column
align – Horizontal alignment of cell content (“left”, “right”, “center”)
head_align – Horizontal alignment of the column header (“left”, “right”, “center”)
visible – Whether the column is visible in the table
wrap – Whether to wrap text content in the column cells
- class DataTableFilter(header: Any | None = None)[source]#
Bases:
objectDefines a filter control for a
wildewidgets.DataTablecolumn.This class represents a UI control for filtering data in a specific column, typically displayed as a dropdown list of options.If no default is provided, the filter is off by default.
Example
from wildewidgets import DataTableFilter # Create a status filter with custom options filter = DataTableFilter( header="Filter by Status", ) filter.add_choice("Active", "active") filter.add_choice("Inactive", "inactive") filter.add_choice("Pending", "pending") # Add the filter to the table table.add_filter("status", filter)
- Keyword Arguments:
header – Optional header content for the filter
- add_choice(label: str, value: str, default: bool = False) None[source]#
Add a filter option to the choices list.
- Parameters:
label – The human-readable label displayed in the UI
value – The value used for filtering when this option is selected
default – Whether this option is the default selected option
- class DataTableForm(table: Any)[source]#
Bases:
objectProvides form handling for bulk actions in a DataTable.
This class integrates form functionality into a DataTable, allowing users to select multiple rows using checkboxes and perform actions on the selected rows, such as delete, approve, or export.
Note
This class is created automatically by the
wildewidgets.DataTableor its subclasses whenwildewidgets.DataTable.form_actionsare defined.You typically do not need to instantiate this class directly.
The form is only visible if the table has
wildewidgets.DataTable.form_actionsdefined. Form actions and URL are retrieved from the table instance.- Parameters:
table – The DataTable instance this form belongs to
- class DataTableStyler(is_row: bool, test_cell: str, cell_value: Any, css_class: str, target_cell: str | None = None)[source]#
Bases:
objectDefines conditional styling rules for DataTable cells or rows.
This class allows you to apply CSS classes to table cells or rows based on the content of a specific cell. It’s used for conditional formatting, like highlighting negative values in red or flagging certain status values.
Example
from wildewidgets import BaseDataTable, DataTableStyler, DataTableColumn # Style the status column with "text-danger" when value is "error" styler = DataTableStyler( is_row=False, test_cell="status", cell_value="error", css_class="text-danger" ) # Style the entire row with "table-warning" when status is "pending" row_styler = DataTableStyler( is_row=True, test_cell="status", cell_value="pending", css_class="table-warning" ) table = BaseDataTable( title="My Data Table", columns=[ DataTableColumn(field="name", verbose_name="Name"), DataTableColumn(field="status", verbose_name="Status"), ], ) table.add_styler(styler) table.add_styler(row_styler)
- Parameters:
is_row – Whether to apply styling to the entire row (True) or just a cell (False)
test_cell – The name of the column to test for the condition
cell_value – The value to compare against for the condition
css_class – The CSS class to apply when the condition is met
- Keyword Arguments:
target_cell – The name of the column to style (if None, uses
test_cell)
Base#
- class BaseDataTable(*args, width: str | None = None, height: str | None = None, title: str | None = None, searchable: bool | None = True, paging: bool | None = True, page_length: int | None = None, small: bool | None = None, buttons: bool | None = None, striped: bool | None = None, hide_controls: bool | None = None, table_id: str | None = None, sort_ascending: bool | None = None, data: list[Any] | None = None, form_actions: Any = None, form_url: str | None = None, ajax_url_name: str | None = None, column_wrap_fields: list[str] | None = None, is_async: bool | None = None, has_select_all: bool | None = None, **kwargs)[source]#
Bases:
Widget,WidgetInitKwargsMixin,DatatableAJAXViewBase class for creating interactive dataTables with sorting, filtering, and pagination.
This class provides the foundation for building powerful data tables with features like:
Client-side or server-side processing
Column sorting and filtering
Pagination
Custom styling and formatting
Action buttons for row operations
Bulk actions through form submissions
The BaseDataTable can operate in two modes:
Synchronous mode: All data is loaded and processed in the browser
Asynchronous mode: Data is loaded via AJAX from the server as needed
Example
from wildewidgets import BaseDataTable class UserTable(BaseDataTable): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_column("username", "Username") self.add_column("email", "Email") self.add_column("date_joined", "Joined") def render_date_joined_column(self, row, column): return row.date_joined.strftime("%Y-%m-%d")
- Parameters:
*args – Positional arguments passed to the parent Widget class
- Keyword Arguments:
title – The title of the table, displayed above the table controls
width – CSS width for the table (default is “100%”)
height – CSS height for the table (optional)
searchable – Whether to show a search input (default is True)
paging – Whether to enable pagination (default is True)
page_length – Number of rows per page (default is 25)
small – Use smaller font and row height (default is False)
buttons – Add export buttons (default is False)
striped – Use alternating row colors (default is False)
hide_controls – Hide pagination and search controls (default is False)
table_id – Custom CSS ID for the table (random if None)
sort_ascending – Default sort order for the table (default is True)
data – Initial data to populate the table (optional, empty by default)
form_actions – List of bulk actions for selected rows (optional)
form_url – URL to submit form actions (optional)
ajax_url_name – URL name for the AJAX endpoint (default is “wildewidgets_json”)
column_wrap_fields – List of fields to wrap in table controls (optional)
is_async – If True, use AJAX to load data when the table is empty
True) ((default is) –
has_select_all – If True and form_actions is set, show a “select all” checkbox in the checkbox column header (default is False)
**kwargs – Keyword arguments for parent Widget class initialization
- add_column(field: str, verbose_name: str | None = None, searchable: bool = True, sortable: bool = True, align: str = 'left', head_align: str = 'left', visible: bool = True, wrap: bool = True) None[source]#
Add a column to the table definition.
This method defines a new column in the table. The table will look for a method named
render_{field}_columnto handle custom rendering of the column’s cell values.- Parameters:
field – The name of the field/attribute to render in this column
verbose_name – Display name for the column header (defaults to capitalized field name)
searchable – Whether this column is included in global search
sortable – Whether the table can be sorted by this column
align – Horizontal alignment for cell content (“left”, “right”, “center”)
head_align – Horizontal alignment for the header cell (“left”, “right”, “center”)
visible – Whether the column is initially visible
wrap – Whether to wrap content in this column
Example
from wildewidgets import BaseDataTable table = BaseDataTable( title="User List", searchable=True, paging=True, page_length=10 ) table.add_column( "created_at", "Created", align="right", sortable=True )
- add_filter(field: str, dt_filter: DataTableFilter) None[source]#
Add a filter control for a specific column.
Filters allow users to narrow down data based on column values.
- Parameters:
field – The name of the field/column to filter
dt_filter – A DataTableFilter instance defining the filter behavior
Example
from wildewidgets import BaseDataTable, DataTableFilter table = BaseDataTable( title="User List", searchable=True, paging=True, page_length=10 ) table.add_filter( "status", DataTableFilter( choices=[("active", "Active"), ("inactive", "Inactive")] ) )
- add_form_action(action: Any) None[source]#
Add a new form action to this table.
Form actions appear in a dropdown when rows are selected via checkboxes.
- Parameters:
action – The form action to add (usually a tuple of label and handler)
- add_row(**kwargs) None[source]#
Add a row to the table’s data.
This method is used for synchronous tables to add data directly.
- Parameters:
**kwargs – Field values as key-value pairs, where keys match column names
Example
from wildewidgets import BaseDataTable table = BaseDataTable( title="User List", searchable=True, paging=True, page_length=10 ) table.add_row( username="johndoe", email="john@example.com", date_joined="2023-01-15" )
- add_styler(styler: DataTableStyler) None[source]#
Add a style rule to the table.
Stylers allow conditional formatting of cells based on their values or the values of other cells in the same row.
- Parameters:
styler – A
wildewidgets.DataTableStylerinstance defining the styling rule
Example
from wildewidgets import BaseDataTable, DataTableStyler table = BaseDataTable( title="User List", searchable=True, paging=True, page_length=10 ) # Style the "status" column red when its value is "error" table.add_styler( DataTableStyler( test_cell="status", test_value="error", css_class="text-danger" ) )
- build_context(**kwargs) dict[str, Any][source]#
Build the context for synchronous table rendering.
This method adds the table’s row data to the context for template rendering. Override this method to customize how data is prepared for the template.
- Parameters:
**kwargs – The template context to update
- Returns:
The updated context with row data
- Return type:
- get_column_number(name: str) int[source]#
Get the numerical index of a column in the table by its name.
This is useful when you need to reference columns in JavaScript operations or when configuring DataTables-specific functionality.
- Parameters:
name – The field name of the column to find
- Returns:
Zero-based index of the column in the table
- Return type:
- Raises:
IndexError – If no column with the given name exists in the table
- get_content(**kwargs) str[source]#
Render the table to HTML.
This method generates the complete HTML for the table by rendering the template with the prepared context.
- Parameters:
**kwargs – Additional context values to include
- Returns:
The rendered HTML for the table
- Return type:
- get_form_actions() Any[source]#
Get the list of form actions defined for this table.
- Returns:
- The
form_actionslist orNoneif no actions are defined
- The
- Return type:
Any
- get_template_context_data(**kwargs) dict[str, Any][source]#
Prepare the complete context for table template rendering.
This method builds the context dictionary with all necessary data for rendering the table template, including configuration, filters, headers, and data mode (async or sync).
- Parameters:
**kwargs – Initial context values
- Returns:
Complete context dictionary for template rendering
- Return type:
- has_form_actions() bool[source]#
Check if this table has form actions defined.
Form actions allow users to perform bulk operations on selected rows by checking the checkboxes and submitting the form.
- Returns:
True if form actions are defined, False otherwise
- Return type:
- remove_filter(field: str) None[source]#
Remove a previously defined filter from a column.
- Parameters:
field – The name of the field/column to remove the filter from
- render_checkbox_column(row: Any, column: str) str[source]#
Render the checkbox column for form actions.
This method generates the HTML for the checkbox in each row when form_actions are enabled. The checkbox uses the row’s ID as its value.
- Parameters:
row – The data object for the current row
column – The column name (always “checkbox”)
- Returns:
HTML for the checkbox input
- Return type:
- column_fields: dict[str, DataTableColumn]#
A mapping of field name to column definition
- column_filters: dict[str, DataTableFilter]#
A mapping of field name to column filter definition
- column_styles: list[DataTableStyler]#
A list of column styles to apply
- datatable_options: dict[str, Any]#
These are options for dataTable itself and get set in the JavaScript constructor for the table.
- form_actions = None#
Whole table form actions. If this is not
None, add a first column with checkboxes to each row, and a form that allows you to choose bulk actions to perform on all checked rows.
- form_url: str = ''#
The URL to which to POST our form actions if
form_actionsis notNone
- has_select_all: bool = False#
If
Trueandform_actionsis set, show a “select all” checkbox in the checkbox column header. Default isFalseso existing tables are unchanged.
Views#
- class BaseDatatableView(model: type[models.Model] | None = None, order_columns: list[str] | None = None, max_display_length: int | None = None, none_string: str | None = None, is_data_list: bool | None = None, escape_values: bool | None = None, **kwargs)[source]#
Bases:
DatatableMixin,JSONResponseViewBase view for handling dataTables.js server-side processing.
This class combines the dataTables.js processing functionality from
DatatableMixinwith the JSON response handling fromwildewidgets.JSONResponseViewto create a complete server-side processing view for dataTables.js.Extend this class and override the necessary methods to create a custom dataTables.js server-side processing view.
- class DatatableAJAXView(model: type[models.Model] | None = None, order_columns: list[str] | None = None, max_display_length: int | None = None, none_string: str | None = None, is_data_list: bool | None = None, escape_values: bool | None = None, **kwargs)[source]#
Bases:
BaseDatatableViewEnhanced view for handling dataTables.js AJAX requests with advanced features.
This class extends
BaseDatatableViewwith additional functionality for:Advanced column configuration parsing
Per-column filtering and searching
Support for dotted attribute notation and relationship traversal
Custom column rendering based on method naming conventions
It’s designed to be extended for specific datatables, with custom filtering and rendering logic implemented through method overrides.
Example
class UserTableView(DatatableAJAXView): model = User columns = ['id', 'username', 'email', 'is_staff', 'date_joined'] def render_is_staff_column(self, row, column): return '✓' if row.is_staff else '✗' def render_date_joined_column(self, row, column): return row.date_joined.strftime('%Y-%m-%d')
- column_specific_searches() list[tuple[str, str]][source]#
Get a list of active per-column search filters.
This method identifies columns that have search values specified in the DataTables request, which happens when a user enters a search term in a specific column’s filter input.
- columns(querydict: dict[str, Any]) dict[str, Any][source]#
Parse dataTables.js column configuration into a more usable format.
This method converts the flattened column configuration from dataTables.js into a nested dictionary structure that’s easier to work with. It maps column data by column name rather than index for more intuitive access.
Note
This overrides the
columnsattribute fromDatatableMixinto provide a more advanced parsing mechanism.
- filter_queryset(qs: models.QuerySet) models.QuerySet[source]#
Apply all filtering to the queryset based on dataTables.js parameters.
This method handles both:
Per-column searches specified by column-specific filters
Global searches from the main dataTables.js search input
- Parameters:
qs – The queryset to filter
- Returns:
The filtered queryset
- Return type:
models.QuerySet
- render_column(row: Any, column: str) str[source]#
Render a column value with custom rendering support.
This method enables custom column rendering through convention-based method naming. If a method named
render_COLUMNNAME_columnexists, it will be called to render the column instead of the default implementation.- Parameters:
row – The model instance or dictionary for this row
column – The column name
- Returns:
The rendered column value
- Return type:
Example
To customize rendering for a ‘status’ column:
def render_status_column(self, row: Model, column: str) -> str: status = row.status if status == 'active': return f'<span class="badge bg-success">{status}</span>' return f'<span class="badge bg-secondary">{status}</span>'
- search(qs: models.QuerySet, value: str) models.QuerySet[source]#
Apply a global search across all searchable columns.
This method is called when a user enters a search term in the main dataTables.js search input. It applies the search across all searchable columns and returns distinct results.
- Parameters:
qs – The queryset to search
value – The search term
- Returns:
The filtered queryset containing only matching records
- Return type:
models.QuerySet
- search_query(qs: models.QuerySet, value: str) Q | None[source]#
Build a Q object for performing global search across multiple columns.
This method constructs a query that searches all searchable columns for the given value, using OR logic to match records that have the value in any searchable column.
- Parameters:
qs – The queryset (not used in the default implementation)
value – The search term to look for
- Returns:
- A Django Q object representing the search, or None if no
searchable columns exist
- Return type:
Q | None
- searchable_columns() list[str][source]#
Get the list of column names that are marked as searchable.
This method parses the column configuration to identify which columns should be included in global searches and per-column filtering. The result is cached for performance.
- single_column_filter(qs: models.QuerySet, column: str, value: str) models.QuerySet[source]#
Apply filtering to a queryset based on a single column search.
This method filters the queryset by a specific column value. It supports:
Custom filtering via
filter_COLUMNNAME_columnmethodsDefault
icontainsfiltering for searchable columns
- Parameters:
qs – The queryset to filter
column – The column name to filter on
value – The search value to filter by
- Returns:
The filtered queryset
- Return type:
models.QuerySet
Example
To implement custom filtering for a specific column:
from django.db.models import QuerySet def filter_status_column( self, qs: QuerySet, column: str, value: str ) -> QuerySet: if value.lower() == 'active': return qs.filter(is_active=True) elif value.lower() == 'inactive': return qs.filter(is_active=False) return qs
- class DatatableMixin(model: type[models.Model] | None = None, order_columns: list[str] | None = None, max_display_length: int | None = None, none_string: str | None = None, is_data_list: bool | None = None, escape_values: bool | None = None, **kwargs)[source]#
Bases:
objectA mixin that provides server-side processing for jQuery DataTables.
This mixin handles all the server-side processing required by jQuery DataTables, including sorting, filtering, searching, and pagination. It can work with Django QuerySets and provides a customizable framework for rendering data.
The mixin works with both older (<1.10) and newer versions of DataTables, automatically adapting to the format of parameters sent by the client.
Example
class MyDatatableView(DatatableMixin, JSONResponseView): model = MyModel columns = ['id', 'name', 'description'] order_columns = ['id', 'name', 'description'] def render_description_column(self, row, column): return f"{row.description[:50]}..."
- extract_datatables_column_data() list[dict[str, str]][source]#
Extract column configuration data from the dataTables.js request.
This method parses the complex column configuration parameters sent by dataTables.js 1.10+ into a more manageable structure for internal use.
- get_columns() list[str][source]#
Get the list of columns to display in the datatable.
This method determines which columns will be included in the response. It first checks the
columnsattribute, then falls back to extracting column information from the dataTables.js request parameters if using newer versions.
- get_context_data(*args, **kwargs)[source]#
Process the DataTables request and prepare the response data.
This is the main entry point that:
Initializes the configuration based on the request
Gets the initial queryset
Applies filtering, sorting, and pagination
Formats the results as expected by DataTables
- Parameters:
*args – Variable length argument list
- Keyword Arguments:
**kwargs – Arbitrary keyword arguments
- Returns:
Response data in the format expected by DataTables
- Return type:
Note
The returned dictionary contains different keys depending on the dataTables.js version in use.
- get_filter_method() str[source]#
Get the preferred Django queryset filter method for searches.
This determines how text searching is performed on columns. By default, uses “istartswith” for case-insensitive prefix matching, but can be overridden to use other methods like “icontains” for substring matching.
- Returns:
The filter method string (e.g., “istartswith”, “icontains”)
- Return type:
- get_initial_queryset() models.QuerySet[source]#
Get the initial queryset for the datatable.
By default, returns all objects from the model specified in the model attribute. Override this method to provide custom querysets, filtering by user permissions, or any other logic needed to determine the base dataset.
- Returns:
The initial queryset for the datatable
- Return type:
QuerySet
- Raises:
NotImplementedError – If no model is specified and this method is not overridden
- get_order_columns() list[str][source]#
Get the list of columns that can be used for ordering/sorting.
This method returns the columns that can be sorted in the datatable. It first checks the
order_columnsattribute, then falls back to extracting column information from the dataTables.js request parameters if using newer versions.
- handle_exception(e: Exception) NoReturn[source]#
Handle exceptions that occur during processing.
This method logs the exception and re-raises it by default. Override this method to implement custom exception handling.
- Parameters:
e – The exception that was raised
- Raises:
Exception – Re-raises the original exception
- initialize(*args, **kwargs)[source]#
Initialize the datatable by determining the DataTables version in use.
This method checks request parameters to detect whether the client is using DataTables <1.10 (which uses different parameter naming conventions), and configures the mixin accordingly.
- Parameters:
*args – Variable length argument list
**kwargs – Arbitrary keyword arguments
- ordering(qs: models.QuerySet) models.QuerySet[Model][source]#
Apply ordering to the queryset based on dataTables.js parameters.
This method parses sorting parameters from the dataTables.js request and applies them to the queryset. It supports multi-column sorting and handles both older and newer dataTables.js parameter formats.
- Parameters:
qs – The queryset to order
- Returns:
The ordered queryset
- Return type:
models.QuerySet
- paging(qs: models.QuerySet) models.QuerySet[source]#
Apply pagination to the queryset based on dataTables.js parameters.
This method extracts pagination parameters (start position and length) from the dataTables.js request and slices the queryset accordingly.
- Parameters:
qs – The queryset to paginate
- Returns:
The paginated queryset
- Return type:
models.QuerySet
- prepare_results(qs: models.QuerySet) list[list[str]] | list[dict[str, Any]][source]#
Transform queryset results into the format expected by dataTables.js.
This method converts Django model instances into either:
Lists of values (when
is_data_listis True)Dictionaries mapping column names to values (when
is_data_listis False)
It calls
render_columnfor each value to allow custom formatting.- Parameters:
qs – The queryset containing the results to display
- Returns:
Either a list of lists (row-based format) or a list of dictionaries (column-based format) depending on the DataTables configuration
- render_column(row: Any, column: str) str[source]#
Render a column value for display in the datatable.
This is the main method for formatting column values. Override this or create methods named
get_FIELDNAME_displayon your Django model to customize how specific columns are displayed. See_render_columnfor details on how to implement custom rendering logic.
- FILTER_ICONTAINS: Final[str] = 'icontains'#
The filter method to use for global searches and single column filtering for case-insensitive “contins” searches
- FILTER_ISTARTSWITH: Final[str] = 'istartswith'#
The filter method to use for global searches and single column filtering for case-insensitive “startswith” searches
- columns_data: list[dict[str, Any]] = []#
This gets set by the dataTables Javascript when it does the AJAX call
- is_data_list: bool = True#
This determines the type of results. If the AJAX call passes us a data attribute that is not an integer, it expects a dictionary with specific fields in the response, see: dataTables columns.data
- max_display_length: int = 100#
The max number of of records that will be returned, so that we can protect our our server from rendering huge amounts of data
- model: type[models.Model] | None = None#
The Django model that this datatable will be based on. If not provided, you must implement the
get_initial_querysetmethod to return a queryset.
Actions#
- class ActionButtonBlockMixin(*args, actions: list[wildewidgets.widgets.tables.actions.RowActionButton] | None = None, button_size: str | None = None, justify: Optional[Literal['start', 'center', 'end']] = None, **kwargs)[source]#
Bases:
objectA mixin for
wildwidgets.DataTableclasses that adds action buttons usingRowActionButtonclasses.This mixin provides a more object-oriented approach to adding action buttons compared to
ActionsButtonsBySpecMixin. It usesRowActionButtoninstances for greater flexibility and extensibility.Important
Typically, you will not use this directly, but rather use
wildewidgets.StandardActionButtonModelTableorwildewidgets.LookupModelTable, which already has this built in as a mixin.Example
from wildewidgets import ActionButtonBlockMixin, DataTable class MyTable(ActionButtonBlockMixin, DataTable): actions = [ RowEditButton(), RowDeleteButton() ] ...
- Parameters:
*args – Positional arguments for the parent class
- Keyword Arguments:
actions – List of
RowActionButtoninstances to add to the “Actions” column. If not provided, a default “View” button is used.button_size – Size of the action buttons (default: None)
justify – Justification of the action buttons in the “Actions” column (default: “end”)
- get_actions() list[wildewidgets.widgets.tables.actions.RowActionButton][source]#
Get the list of action buttons to display.
Override this in subclasses to dynamically determine which buttons to show.
- Returns:
List of action button instances
- Return type:
- get_content(**kwargs) str[source]#
Get the rendered content for the table, including action columns.
- Parameters:
**kwargs – Keyword arguments for content generation
- Returns:
The HTML content for the table
- Return type:
- render_actions_column(row: Any, column: str) str[source]#
Render all action buttons for a specific row.
Creates a horizontal layout containing all visible action buttons for the given row.
- Parameters:
row – The row data to render buttons for
column – The column name (ignored, always “actions”)
- Returns:
Complete HTML for the actions column
- Return type:
Note
Buttons are only shown if their is_visible method returns True for the current user.
- actions: list[wildewidgets.widgets.tables.actions.RowActionButton] = [<wildewidgets.widgets.tables.actions.RowModelUrlButton object>]#
A list of
RowActionButtonsubclasses to display in the “Actions” column.
- class ActionsButtonsBySpecMixin(*args, actions: Any = None, action_button_size: str | None = None, default_action_button_label: str | None = None, default_action_button_color_class: str | None = None, **kwargs)[source]#
Bases:
objectA mixin for
wildewidgets.DataTableclasses and subclasses that adds action buttons based on specifications.This mixin allows you to add action buttons to the rightmost column of a table by specifying them as tuples that define their behavior. It provides a simple way to create standard actions without needing to define button classes.
Actions are specified as tuples with these elements, in this order:
Label (str): The button text
URL name (str): Django URL pattern name, e.g., “app:item-view”. We’ll reverse this to get the URL.
Method (str, optional): “get” or “post” (default: “get”)
Color (str, optional): Bootstrap color class (default: “secondary”)
Field name (str, optional): ID field name (default: “id”)
JS function (str, optional): JavaScript function to call
Example
from wildewidgets import ActionsButtonsBySpecMixin class MyDataTable(ActionsButtonsBySpecMixin, DataTable): actions = [ ("View", "app:item-view"), ("Edit", "app:item-edit", "get", "primary"), ("Delete", "app:item-delete", "post", "danger", "id", "confirmDelete") ]
This will add an “Actions” column with buttons for each specified action. Each button will be rendered with the appropriate URL and method based on the row data.
- Parameters:
*args – Positional arguments for the parent class
- Keyword Arguments:
actions – List of action specifications to add to the table
action_button_size – Size of the action buttons (default: “normal”)
default_action_button_label – Default label for the action button (default: “View”)
default_action_button_color_class – Default color class for the action button (default: “secondary”)
**kwargs – Keyword arguments for the parent class
- get_action_button(row: Any, label: str, url_name: str, method: str = 'get', color_class: str = 'secondary', attr: str = 'id', js_function_name: str | None = None) str[source]#
Create an action button for a specific row using a Django URL name.
- Parameters:
row – The row data this button is for
label – Text to display on the button
url_name – Django URL pattern name to link to
method – HTTP method to use (“get” or “post”)
color_class – Bootstrap color class
attr – Row attribute to use as ID parameter
js_function_name – Optional JavaScript function to call on click
- Returns:
HTML for the rendered button
- Return type:
- get_action_button_url_extra_attributes(row: Any) str[source]#
Get additional URL query parameters for action buttons.
Override this in subclasses to add custom query parameters.
- Parameters:
row – The row data this button is for
- Returns:
Additional URL query parameters
- Return type:
- get_action_button_with_url(row: Any, label: str, url: str, method: str = 'get', color_class: str = 'secondary', attr: str = 'id', js_function_name: str | None = None) str[source]#
Create an action button for a row with a specific URL.
- Parameters:
row – The row data this button is for
label – Text to display on the button
url – Complete URL to link to
method – HTTP method to use (“get” or “post”)
color_class – Bootstrap color class
attr – Row attribute to use as ID parameter for POST forms
js_function_name – Optional JavaScript function to call on click
- Returns:
HTML for the rendered button
- Return type:
- get_conditional_action_buttons(row: Any) str[source]#
Get additional action buttons based on row data.
Override this in subclasses to add buttons conditionally based on row attributes.
- Parameters:
row – The row data to evaluate
- Returns:
HTML for additional buttons
- Return type:
- get_content(**kwargs) str[source]#
Get the rendered content for the table, including action columns.
- Parameters:
**kwargs – Keyword arguments for content generation
- Returns:
The HTML content for the table
- Return type:
- get_template_context_data(**kwargs) dict[str, Any][source]#
Add action column information to the template context.
- Parameters:
**kwargs – Keyword arguments to update
- Returns:
Updated context dictionary with action column information
- Return type:
- render_actions_column(row: Any, column: str) str[source]#
Render all action buttons for a specific row.
This method generates the complete HTML for the actions column, including: 1. The default view button if the model has get_absolute_url 2. All buttons defined in the actions specification 3. Any conditional buttons from get_conditional_action_buttons
- Parameters:
row – The row data to render buttons for
column – The column name (ignored, always “actions”)
- Returns:
Complete HTML for the actions column
- Return type:
- action_button_size: str = 'normal'#
How big should each action button be? One of
normal,btn-lg, orbtn-sm.
- actions: Any = False#
Per row action buttons. If not
False, this will simply add a rightmost column namedActionswith a button nameddefault_action_button_labelwhich when clicked will take the user to the
- class RowActionButton(text: str | None = None, url: str | Callable[[Any], str] | None = None, color: str | None = None, size: str | None = None, permission: str | None = None, **kwargs)[source]#
Bases:
BlockBase class for action buttons displayed in table rows.
This class provides the foundation for creating buttons that appear in the “Actions” column of tables. Each button is bound to a specific row and can perform actions based on that row’s data. Note that all keyword arguments/class attributes from
wildewidgets.Blockare also accepted.You can use this class directly with keyword arguments to create buttons that link to row-specific URLs. In order for this to work, you’ll need to pass a callable into url that accepts a single argument, which will be the row data. This callable should return a string that is the URL for the button.
You will more usually subclass this, setting class attributes to create specific model-based buttons, and overriding the
get_urlmethod to return the URL for the button based on the row data.- url#
The URL the button links to, a Django URL name to reverse, or a callable that accepts a
rowarg and returns a URL string
- row#
Reference to the row data this button is bound to (set by bind method)
Example
Direct usage with keyword arguments:
from django.urls import reverse from wildewidgets import RowActionButton def get_home_url(row: Any) -> str: return reverse("app:home", kwargs={"id": row.id}) button = RowActionButton( text="Home", url=get_home_url, color="primary", permission="app.view_item" )
Subclassing for specific actions:
class RowViewButton(RowActionButton): text = "View" color = "info" size = "sm" url = "core:item-view" def get_url(self, row: Any) -> str: return reverse(self.url, kwargs={"id": row.id})
- Keyword Arguments:
text – The text to display on the button
url – The URL the button should link to
color – The Bootstrap color class for the button (default: “secondary”)
size – The Bootstrap size class for the button (default: None)
permission – Optional Django permission string required to see this button, e.g. “app.view_item”
**kwargs – Additional attributes passed to the parent Block class
- Raises:
ImproperlyConfigured – If ‘text’ or ‘url’ is not provided
- bind(row: Any, table: ActionButtonBlockMixin, size: str | None = None) RowActionButton[source]#
Bind this button to a specific row and return a copy configured for that row.
This method creates a copy of the button configured specifically for the given row, including setting appropriate URLs, colors and sizes.
- Parameters:
row – The row data to bind this button to
table – The table instance that contains this row
size – Optional size override for the button
- Returns:
A new button instance bound to the specified row
- Return type:
Note
The table parameter provides access to table-level properties like CSRF tokens needed for form submissions.
- get_url(row: Any) str[source]#
Get the URL for this button, potentially based on row data.
This base implementation simply returns the static URL property. Subclasses can override this to generate dynamic URLs based on row data.
- Parameters:
row – The row data to use for URL generation
- Returns:
The URL for the button
- Return type:
- is_visible(row: Any, user: AbstractUser | None) bool[source]#
Determine if this button should be visible to the given user.
- Parameters:
row – The row data this button is associated with
user – The current Django user
- Returns:
True if the button should be visible, False otherwise
- Return type:
Note
If a permission is specified, the user must have that permission for the button to be visible.
- row: Any#
The table will set this
- class RowDeleteButton(form_fields: list[str] | None = None, confirm_text: str | None = None, **kwargs)[source]#
Bases:
RowFormButtonA pre-configured button for deleting a row’s model instance.
This is a convenience subclass of RowFormButton configured specifically for delete operations. It submits the row’s ID via POST to the URL returned by the model’s
get_delete_urlmethod by default.Either subclass this, setting class attributes to create specific model-based buttons, or use it directly with keyword arguments to create buttons that link to model-specific URLs. Note that all keyword arguments/class attributes from
wildewidgets.BlockandRowModelUrlButtonare also accepted.Important
Your model must implement a method or attribute named
attribute, which must return the URL to submit the form to for deletion. By default, this isget_delete_url.The form submitted will have by default the following fields:
csrf_token: CSRF token for securityid: The ID of the row’s model instance
Thus, your delete view should expect a POST request with these fields.
Note
The confirmation text is generated using the row’s string representation, so ensure your model has a meaningful __str__ method. If you need a custom confirmation message, subclass and override
get_confirm_text.Example
Direct usage with keyword arguments:
from wildewidgets import RowDeleteButton # Simple usage - requires model.get_delete_url() to exist button = RowDeleteButton()
Subclassing for specific actions:
- class RowCustomDeleteButton(RowDeleteButton):
attribute = “get_custom_delete_url” text = “Remove” color = “danger” form_fields = [“id”, “name”] # Submit additional fields
- get_confirm_text(row: Any) str[source]#
Generate a confirmation message for deleting this row.
Creates a message like ‘Delete “Item Name”?’ using the row’s string representation.
- Parameters:
row – The row data to create a confirmation message for
- Returns:
The confirmation message to display
- Return type:
- class RowDjangoUrlButton(url_path: str | None = None, url_args: list[str] | None = None, url_kwargs: dict[str, str] | None = None, **kwargs)[source]#
Bases:
RowActionButtonA row action button that constructs its URL using Django’s URL resolver.
This button uses Django’s URL resolution system with either positional or keyword arguments to construct its URL dynamically based on row data.
Either subclass this, setting class attributes to create specific model-based buttons, or use it directly with keyword arguments to create buttons that link to model-specific URLs. Note that all keyword arguments/class attributes from
wildewidgets.BlockandRowActionButtonare also accepted.Example
Direct usage with keyword arguments:
from wildewidgets import RowDjangoUrlButton # Using positional arguments (e.g., 'item/1/') button = RowDjangoUrlButton( text="Edit", url_path="app:item-edit", url_args=["id"] ) # Using keyword arguments (e.g., 'item/edit/?pk=1') button = RowDjangoUrlButton( text="Edit", url_path="app:item-edit", url_kwargs={"pk": "id"} )
Subclassing for specific actions:
class RowEditButton(RowDjangoUrlButton): url_path = "app:item-edit" text = "Edit" color = "primary" url_args = ["id"]
Note
You must specify either
url_argsorurl_kwargs, but not both.- Keyword Arguments:
url_path – The Django URL pattern name to reverse
url_args – List of row attribute names to use as positional arguments
url_kwargs – Dictionary mapping URL param names to row attribute names
- Raises:
ImproperlyConfigured – If both
url_argsandurl_kwargsare provided, or if url_path is not setRowActionButton.RequiredAttrOrKwarg – If url_path is not set
- class RowEditButton(attribute: str | None = None, **kwargs)[source]#
Bases:
RowModelUrlButtonA pre-configured button for editing a row’s model instance.
This is a convenience subclass of RowModelUrlButton configured specifically for edit operations. It looks for a get_update_url method on the model.
Either subclass this, setting class attributes to create specific model-based buttons, or use it directly with keyword arguments to create buttons that link to model-specific URLs. Note that all keyword arguments/class attributes from
wildewidgets.BlockandRowModelUrlButtonare also accepted.- attribute#
The model method to call for URL (“get_update_url”). Your model must implement this method or attribute to return the URL for editing.
- Type:
Example
Direct usage with keyword arguments:
from wildewidgets import RowEditButton # Simple usage - requires model.get_update_url() to exist button = RowEditButton() # Custom text button = RowEditButton(text="Modify")
Subclassing for specific actions:
- class RowCustomEditButton(RowEditButton):
attribute = “get_custom_update_url” text = “Modify” color = “warning” url_args = [“id”]
- class RowFormButton(form_fields: list[str] | None = None, confirm_text: str | None = None, **kwargs)[source]#
Bases:
RowModelUrlButtonA row action button that renders as a form, submitting via POST.
This button renders as an HTML form that submits via POST when clicked. It’s ideal for actions that modify data, like delete or status change operations. You do not need to provide a form – it will be created automatically.
Either subclass this, setting class attributes to create specific model-based buttons, or use it directly with keyword arguments to create buttons that link to model-specific URLs. Note that all keyword arguments/class attributes from
wildewidgets.BlockandRowModelUrlButtonare also accepted.Example
Direct usage with keyword arguments:
from wildewidgets import RowFormButton button = RowFormButton( text="Delete", attribute="get_delete_url", form_fields=["id"], confirm_text="Are you sure you want to delete this item?" )
Subclassing for specific actions:
class RowDeleteButton(RowFormButton): attribute = "get_delete_url" text = "Delete" color = "outline-secondary" form_fields = ["id"] confirm_text = "Are you sure you want to delete this item?"
Note
Requires both form_fields and confirm_text to be specified
Will include CSRF token automatically
The form action URL is determined by the
attributemethod or attribute, which must be present on the model class. If you need more sophisticated URL handling, subclass and override theget_urlmethod.
- Keyword Arguments:
form_fields – List of row attribute names to include as hidden fields
confirm_text – Confirmation message to show before submission
- Raises:
ImproperlyConfigured – If form_fields or confirm_text are not set
- bind(row: Any, table: Any, size: str | None = None) RowFormButton[source]#
Bind this button to a specific row and create a form.
Creates a complete form with:
CSRF token
Hidden fields with row data
Submit button with confirmation dialog
- Parameters:
row – The row data to bind this button to
table – The table instance that contains this row
size – Optional size override for the button
- Returns:
A configured form button for the specified row
- Return type:
- get_confirm_text(row: Any) str[source]#
Get the confirmation text for this button.
- Parameters:
row – The row data this button is associated with
- Returns:
The confirmation text to display
- Return type:
- class RowLinkButton(text: str | None = None, url: str | Callable[[Any], str] | None = None, color: str | None = None, size: str | None = None, permission: str | None = None, **kwargs)[source]#
Bases:
RowActionButtonA row action button that renders as a link with appropriate attributes.
This subclass of
RowActionButtonensures the rendered button has the appropriate attributes for accessibility and behavior as a link.Either subclass this, setting class attributes to create specific model-based buttons, or use it directly with keyword arguments to create buttons that link to model-specific URLs. Note that all keyword arguments/class attributes from
wildewidgets.BlockandRowActionButtonare also accepted.Note
If
rowis going to be a Django model instance, you’re better off usingRowModelUrlButtonorRowDjangoUrlButtoninstead.Honestly, the only difference between this and
RowActionButtonis that we set theroleattribute on the <a> tag to “button”.- Inherits all attributes from :py:class:`RowActionButton`.
Example
Direct usage with keyword arguments:
from django.urls import reverse from wildewidgets import RowLinkButton def get_details_url(row: Any) -> str: return reverse("app:item-details", kwargs={"id": row.id}) button = RowLinkButton( text="Details", url=get_details_url, color="info" )
Subclassing for specific actions:
from django.urls import reverse_lazy from wildewidgets import RowLinkButton class RowDetailsButton(RowLinkButton): text = "Details" color = "info" def get_url(self, row: Any) -> str: return reverse("app:item-details", kwargs={"id": row.id})
- get_context_data(*args, **kwargs) dict[str, Any][source]#
Prepare the context data for template rendering.
Sets appropriate attributes for accessibility including href and role.
- Parameters:
*args – Positional arguments passed to the parent method
**kwargs – Keyword arguments passed to the parent method
- Returns:
The context dictionary with updated attributes
- Return type:
- class RowModelUrlButton(attribute: str | None = None, **kwargs)[source]#
Bases:
RowActionButtonA row action button that gets its URL from a model instance attribute or method.
This button uses a specified attribute or method of the row’s model instance to determine its URL, making it ideal for standard model actions like view or edit.
Either subclass this, setting class attributes to create specific model-based buttons, or use it directly with keyword arguments to create buttons that link to model-specific URLs. Note that all keyword arguments/class attributes from
wildewidgets.BlockandRowActionButtonare also accepted.- attribute#
The model attribute or method to use for URL generation. Your model must implement this method or attribute to return the URL.
- Type:
Example
Direct usage with keyword arguments:
from wildewidgets import RowModelUrlButton # Uses row.get_absolute_url() to determine URL button = RowModelUrlButton(text="View Details") # Uses row.get_edit_url() to determine URL button = RowModelUrlButton( text="Edit", attribute="get_edit_url", color="primary" )
Subclassing for specific actions:
class RowViewButton(RowModelUrlButton): attribute = "get_absolute_url" text = "View" color = "info" size = "sm"
- Keyword Arguments:
attribute – The model attribute or method to use for URL generation. Your model must implement this method or attribute to return the URL.
**kwargs – Additional keyword arguments for the *
RowActionButtonclass
- get_url(row: Any) str[source]#
Get the URL from the specified model attribute or method.
- Parameters:
row – The model instance to get the URL from
- Returns:
The URL for the button
- Return type:
- Raises:
ValueError – If the specified attribute doesn’t exist on the model
- class StandardModelActionButtonBlockMixin(*args, actions: list[wildewidgets.widgets.tables.actions.RowActionButton] | None = None, button_size: str | None = None, justify: Optional[Literal['start', 'center', 'end']] = None, **kwargs)[source]#
Bases:
ActionButtonBlockMixinA ready-to-use mixin providing standard “Edit” and “Delete” buttons for model tables.
This mixin provides a convenient configuration of
ActionButtonBlockMixinwith “Edit” and “Delete” buttons pre-configured. It’s a quick way to add these common actions to any DataTable.Note
This is used by
wildewidgets.LookupModelTable.- Requirements:
Your model must implement
get_absolute_url,get_update_urlandget_delete_urlmethods
Example
from wildewidgets import StandardModelActionButtonBlockMixin, DataTable from myapp.models import MyModel class MyTable(StandardModelActionButtonBlockMixin, DataTable): model = MyModel fields = ["name", "description"] # No additional configuration needed for basic edit/delete buttons
- actions: list[wildewidgets.widgets.tables.actions.RowActionButton] = [<wildewidgets.widgets.tables.actions.RowModelUrlButton object>, <wildewidgets.widgets.tables.actions.RowModelUrlButton object>]#
A list of
RowActionButtonsubclasses to display in the “Actions” column.