from django.utils.safestring import mark_safe from django.db import models from django.template.defaultfilters import yesno, linebreaksbr, urlize from django.utils.translation import get_date_formats from django.utils.text import capfirst from django.utils import dateformat class ModelInfo(object): class _Meta: model = None fields = () exclude = () sections = None row_template = '%s%s' show_if_none = False auto_urlize = True auto_linebreaks = True def __init__(self, instance, *args, **kwargs): self.instance = instance self._meta = self.Meta() _meta = self._Meta() for attr in ('model','fields','exclude','sections','row_template','show_if_none', 'auto_urlize','auto_linebreaks',): if not hasattr(self._meta, attr): setattr(self._meta, attr, getattr(_meta, attr)) def get_model_fields(self): return [f.name for f in self._meta.model._meta.fields \ if f.name != 'id' and \ (f.name in self._meta.fields or \ not f.name in self._meta.exclude)\ ] def get_field(self, f_name): return [f for f in self._meta.model._meta.fields if f.name == f_name][0] def get_field_display_text(self, f_name): return self.get_field(f_name).verbose_name def get_field_display_value(self, f_name): field = self.get_field(f_name) try: return getattr(self, 'get_%s_value'%f_name) except: pass f_value = getattr(self.instance, f_name) if f_value is None: return None if callable(f_value): return f_value() if isinstance(f_value, models.Model): if self._meta.auto_urlize and hasattr(f_value, 'get_absolute_url'): return '%s'%(f_value.get_absolute_url(), f_value) else: return unicode(f_value) if field.choices: return dict(field.choices).get(f_value, None) if isinstance(field, models.BooleanField): return yesno(f_value) date_format, datetime_format, time_format = get_date_formats() if isinstance(field, models.DateTimeField): return capfirst(dateformat.format(f_value, datetime_format)) if isinstance(field, models.TimeField): return capfirst(dateformat.time_format(f_value, time_format)) if isinstance(field, models.DateField): return capfirst(dateformat.format(f_value, date_format)) if isinstance(field, models.TextField): if self._meta.auto_urlize: f_value = urlize(f_value) if self._meta.auto_linebreaks: f_value = linebreaksbr(f_value) return f_value def as_string(self): ret = [] sections = self._meta.sections or ((None, self._meta.fields or self.get_model_fields()),) for s_name, s_fields in sections: if s_name: ret.append(self._meta.row_template%(' ', '

%s

'%s_name)) for f_name in s_fields: f_display = self.get_field_display_text(f_name) f_display = f_display[0] == f_display[0].lower() and f_display.capitalize() or f_display f_value = self.get_field_display_value(f_name) if self._meta.show_if_none or f_value is not None: ret.append(self._meta.row_template%(f_display, f_value)) return mark_safe('\n'.join(ret)) def __unicode__(self): return self.as_string()