# Exports
__all__ = (
"Datum",
"Record",
)
# Classes
[docs]class Datum(object):
"""A specific piece of information to be displayed to a user.
.. tip::
This is equivalent to a `td` in an HTML table.
"""
[docs] def __init__(self, name, value, default=None, display_value=None, field_type=None, help_text=None, label=None,
preview_value=None, **kwargs):
"""Initialize a datum instance.
:param name: The name of the field.
:type name: str
:param value: The "raw" value of the field from the database.
:param default: The default value if any.
:param display_value: The human-friendly value to be displayed to users.
:type display_value: str
:param field_type: The type of field.
:type field_type: str
:param help_text: The field's help text.
:type help_text: str | HelpText
:param label: The field's label, e.g. verbose name.
:type label: str
:param preview_value: The preview value of the field, if any.
:type preview_value: str
.. note::
Additional keyword arguments are available as dynamic attributes.
"""
self.attributes = kwargs
self.default = default
self.display_value = display_value
self.field_type = field_type or "field"
self.help_text = help_text
self.label = label or name.replace("_", " ").title()
self.name = name
self.preview_value = preview_value
self.value = value
def __getattr__(self, item):
return self.attributes.get(item)
def __repr__(self):
return "<%s %s:%s>" % (self.__class__.__name__, self.name, self.field_type)
def __str__(self):
return self.to_string()
[docs] def to_string(self):
"""Get the datum as a string.
:rtype: str
"""
if self.display_value:
return str(self.display_value)
if self.value:
return str(self.value)
if self.default is not None:
return str(self.default)
return ""
@property
def type(self):
"""Alias for ``field_type``."""
return self.field_type
[docs]class Record(object):
"""A collection of data (``Datum``) instances, e.g. a row.
.. tip::
This is equivalent to a ``tr`` in an HTML table.
"""
[docs] def __init__(self, identifier, instance, actions=None, attributes=None, css=None, data=None, dictionary=None,
display_name=None, meta=None, record_type=None, url=None, **kwargs):
"""Initialize a record instance.
:param identifier: The unique record identifier, e.g. the primary key of the model.
:type identifier: int | str
:param actions: Row-level actions that may be performed on the record.
:type actions: list[Action]
:param attributes: Record attributes that may be flattened as part of the HTMl output.
:type attributes: dict
:param css: CSS classes to be applied to the output.
:type css: list | str
:param data: A list of datum instances included in the record. See also ``add()`` and ``append()``.
:type date: list[Datum]
:param display_name: The human-friendly name of the record.
:type display_name: str
:param record_type: The type of record, e.g. ``record._meta.model_name``.
:type record_type: str
.. note::
Additional keyword arguments are available as properties of the record.
"""
self.actions = actions
self.attributes = attributes or dict()
self.data = data or list()
self.dictionary = dictionary or dict()
self.display_name = display_name
self.identifier = identifier
self.instance = instance
self.meta = meta
self.properties = kwargs
# noinspection PyProtectedMember
self.type = record_type or instance._meta.model_name
self.url = url
# Handle record CSS.
if type(css) is list:
_classes = css
elif type(css) is str:
_classes = [css]
else:
_classes = list()
_classes.append("ui-record")
# Handle attributes.
if "class" in self.attributes:
self.attributes['class'] += " ".join(_classes)
else:
self.attributes['class'] = " ".join(_classes)
self.attributes['data-id'] = identifier
self.attributes['data-type'] = self.type
def __getattr__(self, item):
if item in self.dictionary:
return self.dictionary.get(item)
return getattr(self.instance, item, None)
def __iter__(self):
return iter(self.data)
def __len__(self):
return len(self.data)
def __repr__(self):
return "<%s %s:%s>" % (self.__class__.__name__, self.type, self.identifier)
def __str__(self):
return self.to_string()
[docs] def add(self, name, value, default=None, display_value=None, field_type=None, help_text=None, label=None,
preview_value=None, **kwargs):
"""Add datum to the record's data by creating a new Datum instance.
See :py:class:`Datum`.
:rtype: Datum
"""
datum = Datum(
name,
value,
default=default,
display_value=display_value,
field_type=field_type,
help_text=help_text,
label=label,
preview_value=preview_value,
**kwargs
)
self.data.append(datum)
return datum
[docs] def append(self, datum):
"""Add a datum instance to the record's data.
:param datum: The instance to be added.
:type datum: Datum
:raise: TypeError
"""
if not isinstance(datum, Datum):
raise TypeError("Datum given to %s record is not Datum instance." % self.record_type)
self.data.append(datum)
[docs] def get_absolute_url(self):
"""Get the ``url`` attribute. Simulates a model instance.
:rtype: str
"""
return self.url or ""
[docs] def to_string(self):
"""Get the display name of the record or the string value of the first Datum instannce in the list.
:rtype: str
"""
if self.display_name is not None:
return self.display_name
return str(self.data[0])