diff --git a/djadmin2/renderers.py b/djadmin2/renderers.py new file mode 100644 index 0000000..0454eaa --- /dev/null +++ b/djadmin2/renderers.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +""" +This module contains default renderers for admin fields. They are used for +example in the list view. +""" +from __future__ import division, absolute_import, unicode_literals + +import os.path +from datetime import date, time, datetime + +from django.utils import formats, timezone +from django.template.loader import render_to_string + +from djadmin2 import settings + + +def boolean_renderer(value, field): + """ + Render a boolean value as icon. + + This uses the template ``renderers/boolean.html``. + + :param value: The value to process. + :type value: boolean + :param field: The model field instance + :type field: django.db.models.fields.Field + :rtype: unicode + + """ + # TODO caching of template + tpl = os.path.join(settings.ADMIN2_THEME_DIRECTORY, 'renderers/boolean.html') + return render_to_string(tpl, {'value': value}) + + +def datetime_renderer(value, field): + """ + Localize and format the specified date. + + :param value: The value to process. + :type value: datetime.date or datetime.time or datetime.datetime + :param field: The model field instance + :type field: django.db.models.fields.Field + :rtype: unicode + + """ + if isinstance(value, datetime): + return formats.localize(timezone.template_localtime(value)) + elif isinstance(value, (date, time)): + return formats.localize(value) + else: + return value + + +def title_renderer(value, field): + """ + Render a string in title case (capitalize every word). + + :param value: The value to process. + :type value: str or unicode + :param field: The model field instance + :type field: django.db.models.fields.Field + :rtype: unicode + + """ + return unicode(value).title() diff --git a/djadmin2/settings.py b/djadmin2/settings.py index 4df39e5..d0ae587 100644 --- a/djadmin2/settings.py +++ b/djadmin2/settings.py @@ -6,6 +6,7 @@ from django.conf import settings MODEL_ADMIN_ATTRS = ( 'list_display', 'list_display_links', 'list_filter', 'admin', 'search_fields', + 'field_renderers', 'index_view', 'detail_view', 'create_view', 'update_view', 'delete_view', 'get_default_view_kwargs', 'get_list_actions', 'actions_on_bottom', 'actions_on_top', diff --git a/djadmin2/templates/djadmin2/bootstrap/model_list.html b/djadmin2/templates/djadmin2/bootstrap/model_list.html index ed52611..32bfc42 100644 --- a/djadmin2/templates/djadmin2/bootstrap/model_list.html +++ b/djadmin2/templates/djadmin2/bootstrap/model_list.html @@ -84,12 +84,12 @@ {% for attr in view.model_admin.list_display %} {% if permissions.has_change_permission %} - {{ obj|get_attr:attr }} + {% render obj attr %} {% else %} {% if permissions.has_view_permission %} - {{ obj|get_attr:attr }} + {% render obj attr %} {% else %} - {{ obj|get_attr:attr }} + {% render obj attr %} {% endif %} {% endif %} diff --git a/djadmin2/templates/djadmin2/bootstrap/renderers/boolean.html b/djadmin2/templates/djadmin2/bootstrap/renderers/boolean.html new file mode 100644 index 0000000..4edf8c8 --- /dev/null +++ b/djadmin2/templates/djadmin2/bootstrap/renderers/boolean.html @@ -0,0 +1,5 @@ +{% if value %} + +{% else %} + +{% endif %} diff --git a/djadmin2/templatetags/admin2_tags.py b/djadmin2/templatetags/admin2_tags.py index a4dbe46..a8a1367 100644 --- a/djadmin2/templatetags/admin2_tags.py +++ b/djadmin2/templatetags/admin2_tags.py @@ -106,3 +106,32 @@ def get_attr(record, attribute_name): if callable(attribute): return attribute() return attribute + + +@register.simple_tag(takes_context=True) +def render(context, model_instance, attribute_name): + """ + This filter applies all renderers specified in admin2.py to the field. + """ + # Get the right value for the attribute. Handle special cases like + # callables and the __str__ attribute. + if attribute_name == '__str__': + value = unicode(model_instance) + else: + attribute = getattr(model_instance, attribute_name) + value = attribute() if callable(attribute) else attribute + + # Get renderer + admin = context['view'].model_admin + renderer = admin.field_renderers.get(attribute_name) + if not renderer: + return value + + # Apply renderer and return value + try: + field = model_instance._meta.get_field_by_name(attribute_name)[0] + except FieldDoesNotExist: + # There is no field with the specified name. + # It must be a method instead. + field = None + return renderer(value, field) diff --git a/djadmin2/types.py b/djadmin2/types.py index ce5694d..64ecafe 100644 --- a/djadmin2/types.py +++ b/djadmin2/types.py @@ -63,15 +63,18 @@ class ModelAdmin2(object): # TODO: Confirm that this is what the Django admin uses list_fields = [] - #This shows up on the DocumentListView of the Posts + # This shows up on the DocumentListView of the Posts list_actions = [actions.DeleteSelectedAction] # This shows up in the DocumentDetailView of the Posts. document_actions = [] - # shows up on a particular field + # Shows up on a particular field field_actions = {} + # Defines custom field renderers + field_renderers = {} + fields = None exclude = None fieldsets = None