from django.core.exceptions import ImproperlyConfigured from django.utils.safestring import mark_safe from django.utils.formats import date_format, time_format from django.utils.timezone import localtime from django_tables2 import Column from django_tables2.columns import library from django_tables2.columns.linkcolumn import BaseLinkColumn from django_tables2.utils import Accessor from viewsets import CrudViewset import six import pytz import urllib #import logging #logger = logging.getLogger('console') def render_image_column(url, width=None, height=None, max_width=None, max_height=None, allow_shrink=True, background_position='center', background_size='contain'): if max_width is not None: if max_height is not None: if not allow_shrink or (width is None) or (height is None): width = max_width height = max_height elif (width > max_width) or (height > max_height): if width * max_height > height * max_width: height = height * max_width / width width = max_width else: width = width * max_height / height height = max_height elif (width is not None) and ((width > max_width) or not allow_shrink): height = height * max_width / width width = max_width elif max_height is not None: if (height is not None) and ((height > max_height) or not allow_shrink): width = width * max_height / height height = max_height if (width is None) or (height is None): raise ImproperlyConfigured('Insufficient information to determine image width and height') return mark_safe('
' % (width, height, url, urllib.quote(background_position), urllib.quote(background_size))) @library.register class ImageColumn(Column): def __init__(self, width_accessor=None, height_accessor=None, max_width=None, max_height=None, allow_shrink=True, background_size='contain', background_position='center', **extra): super(ImageColumn, self).__init__(**extra) if not (width_accessor is None or isinstance(width_accessor, six.string_types) or callable(width_accessor)): raise TypeError('width_accessor must be a string or callable, not %s' % type(accessor).__name__) if not (height_accessor is None or isinstance(height_accessor, six.string_types) or callable(height_accessor)): raise TypeError('height_accessor must be a string or callable, not %s' % type(accessor).__name__) self.width_accessor = Accessor(width_accessor) if width_accessor else None self.height_accessor = Accessor(height_accessor) if height_accessor else None self.max_width = max_width self.max_height = max_height self.allow_shrink = allow_shrink self.background_size = background_size self.background_position = background_position def render(self, record, value, bound_column): width = None if self.width_accessor is None else self.width_accessor.resolve(record) height = None if self.height_accessor is None else self.height_accessor.resolve(record) return render_image_column(value.url, width=width, height=height, max_width=self.max_width, max_height=self.max_height, allow_shrink=self.allow_shrink, background_position=self.background_position, background_size=self.background_size) class DateTimeColumnBase(Column): def __init__(self, format=None, short=True, timezone=None, use_user_timezone=False, timezone_accessor=None, **extra): super(DateTimeColumnBase, self).__init__(**extra) if not (timezone_accessor is None or isinstance(timezone_accessor, six.string_types) or callable(timezone_accessor)): raise TypeError('timezone_accessor must be a string or callable, not %s' % type(accessor).__name__) self.timezone = timezone self.use_user_timezone = use_user_timezone self.timezone_accessor = Accessor(timezone_accessor) if timezone_accessor else None if format is None: if short: if self.SHORT_FORMAT is None: raise ImproperlyConfigured('%s does not provide a short format' % self.__class__.__name__) self.format = self.SHORT_FORMAT else: self.format = self.LONG_FORMAT else: self.format = format def convert_value(self, record, value, bound_column): if self.timezone is not None: tz = self.timezone elif self.use_user_timezone: tz = pytz.timezone(bound_column._table.view.request.user.time_zone()) elif self.timezone_accessor is not None: tz = pytz.timezone(self.timezone_accessor.resolve(record)) else: # Default to Django's idea of local time tz = None return localtime(value, tz) @library.register class CrudLinkColumn(BaseLinkColumn): def __init__(self, view_type=None, attrs=None, **extra): super(CrudLinkColumn, self).__init__(attrs, **extra) self.view_type = view_type def render(self, record, value, bound_column): table = bound_column._table return self.render_link( table.viewset.get_view_url(table.viewset.instance_breadcrumb_view_type if self.view_type is None else self.view_type, table.view, table.GET, record), record=record, value=value ) @library.register class CrudRelativeLinkColumn(BaseLinkColumn): def __init__(self, url_name_suffix, kwargs_callable=None, pk_url_kwarg=None, remove_url_name_components=0, attrs=None, **extra): super(CrudRelativeLinkColumn, self).__init__(attrs, **extra) self.url_name_suffix = url_name_suffix self.kwargs_callable = kwargs_callable self.pk_url_kwarg = pk_url_kwarg self.remove_url_name_components = remove_url_name_components def render(self, record, value, bound_column): table = bound_column._table if self.kwargs_callable is not None: kwargs = self.kwargs_callable(table.view, record, value) elif self.pk_url_kwarg is not None: kwargs = {self.pk_url_kwarg: record.pk} else: kwargs = None return self.render_link( table.viewset.get_relative_view_url(self.url_name_suffix, remove_url_name_components=self.remove_url_name_components, kwargs=kwargs, query_params=table.GET), record=record, value=value ) @library.register class DateColumnEx(DateTimeColumnBase): SHORT_FORMAT = 'SHORT_DATE_FORMAT' LONG_FORMAT = 'DATE_FORMAT' def render(self, record, value, bound_column): if value is None: return bound_column.default return date_format(self.convert_value(record, value, bound_column), self.format) @library.register class DateTimeColumnEx(DateColumnEx): SHORT_FORMAT = 'SHORT_DATETIME_FORMAT' LONG_FORMAT = 'DATETIME_FORMAT' @library.register class TimeColumnEx(DateTimeColumnBase): SHORT_FORMAT = None LONG_FORMAT = 'TIME_FORMAT' def render(self, record, value, bound_column): if value is None: return bound_column.default return time_format(self.convert_value(record, value, bound_column), self.format)