Source code for superdjango.ui.runtime.lists

# Imports

from collections import OrderedDict
import logging
from ..constants import LOCATION, PAGINATION

log = logging.getLogger(__name__)

# Exports

__all__ = (
    "CurrentOrdering",
    "CurrentPagination",
    "ListObject",
)

# Classes


[docs]class CurrentOrdering(object): """Represents the current ordering of a list based on field keywords and values in GET."""
[docs] def __init__(self, request, direction="asc", fields=None, initial_field=None): """Initialize the current ordering. :param direction: The default ordering direction for the initial field; ``asc`` or ``desc``. :type direction: str :param request: The current request instance. :param fields: A list of fields by which the list may be ordered. See :py:class:`Ordering`. :type fields: list[str] :param initial_field: The name of the field to by which ordering should be initially provided. :type initial_field: str .. important:: The ``initial_field`` *must* be part of ``fields``. """ self.direction = direction self.fields = OrderedDict() if fields is not None: # Check the request and add current ordering. for key, value in request.GET.items(): if key in fields: self.fields[key] = value # Set any fields that are not represented in GET to None. for f in fields: if f not in self.fields: self.fields[f] = None try: if initial_field is not None and self.fields[initial_field] is None: self.fields[initial_field] = direction except KeyError: log.error("The initial_field is not part of the provided ordering fields: %s" % initial_field)
def __repr__(self): return "<%s %s>" % (self.__class__.__name__, " ".join(self.fields.keys())) @property def exists(self): """Determine if an ordering keywords exist in ``request.GET``. :rtype: bool """ count = 0 for field_name in self.fields: if self.fields[field_name] is not None: count += 1 return count > 0
[docs] def get_icon(self, field): """Get the FontAwesome icon classes for the given field based on its current status in ordering. :rtype: str """ if field not in self.fields: return "" current = self.fields[field] if current == "asc": return "fas fa-sort-down" elif current == "desc": return "fas fa-sort-up" else: return "fas fa-sort"
[docs] def get_keyword(self, field): """Get the GET keyword and value for the field based on its current status in ordering. :rtype: str """ if field not in self.fields: return "" current = self.fields[field] if current == "desc": return "%s=asc" % field elif current == "asc": return "%s=desc" % field else: return "%s=%s" % (field, self.direction)
[docs]class CurrentPagination(object): """Contains the current pagination options for a list."""
[docs] def __init__(self, page, request, current_limit=None, keyword=PAGINATION.KEYWORD, limit=None, location=LOCATION.DEFAULT, paginator=None, style=PAGINATION.PREVIOUS_NEXT, widget=None): """Initialize current pagination. :param page: The page instance. :type page: Page :param request: The current HTTP request instance. This is *not* assigned as an attribute, but is used to establish the current pagination fragments from GET. :param current_limit: The current limit. :type current_limit: int | Limit :param keyword: The GET keyword used to identify paged results. :type keyword: str :param limit: The limit instance provided by pagination options. See ``get()`` :py:class:`UIListView`` for its usage. :type limit: Limit :param location: The location of the navigation. :type location: str :param paginator: The paginator instance. :type paginator: Paginator :param style: The style of the navigation. :type style: str :param widget: NOT IMPLEMENTED """ self.current_limit = current_limit self.has_next = page.has_next self.has_previous = page.has_previous self.keyword = keyword self.limit = limit self.location = location self.next_page_number = page.next_page_number self.number = page.number self.page = page self.paginator = paginator self.previous_page_number = page.previous_page_number self.style = style self.widget = widget self.url = "" for key, value in request.GET.items(): if key != keyword: self.url += "&%s=%s" % (key, value)
[docs]class ListObject(object): """Serves as a container of records to be displayed in a list of any type or output format."""
[docs] def __init__(self, records, list_type, template, attributes=None, empty_message=None, properties=None): """Initialize the list object. :param records: The records included in the list. :type records: list | QuerySet :param list_type: The type of list that is currently being displayed. :type list_type: str :param template: The template to use for rendering the list. :type template: str :param attributes: Additional attributes that may be included or used when rendering the list. :type attributes: dict :param empty_message: The message to display if the list contains no records. :type empty_message: str :param properties: Additional properties to be accessible as attributes of the list object instance. :type properties: dict """ self.attributes = attributes or dict() self.empty_message = empty_message self.properties = properties or dict() self.records = records self.template = template self.type = list_type self.url = "?list_type=%s" % list_type
def __getattr__(self, item): return self.properties.get(item) def __iter__(self): return iter(self.records) # BUG: When __len__ is enabled on ListObject (and no records exist) the model_list template reports that the list is # not configured. This was extremely hard to troubleshoot! def __len__(self): return len(self.records)
[docs] def get_context_name(self): """Get the type of list. Used in the template context to potentially determine how the list is to be displayed. :rtype: str """ return self.type