|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +""" from https://github.com/chrisglass/django_polymorphic/blob/master/polymorphic/showfields.py |
| 3 | +""" |
| 4 | + |
| 5 | +from django.db import models |
| 6 | +from django.utils import six |
| 7 | + |
| 8 | + |
| 9 | +class ShowFieldBase(object): |
| 10 | + """ base class for the ShowField... model mixins, does the work """ |
| 11 | + |
| 12 | + polymorphic_query_multiline_output = True # cause nicer multiline PolymorphicQuery output |
| 13 | + |
| 14 | + polymorphic_showfield_type = False |
| 15 | + polymorphic_showfield_content = False |
| 16 | + |
| 17 | + # these may be overridden by the user |
| 18 | + polymorphic_showfield_max_line_width = None |
| 19 | + polymorphic_showfield_max_field_width = 20 |
| 20 | + polymorphic_showfield_old_format = False |
| 21 | + |
| 22 | + def __repr__(self): |
| 23 | + return self.__unicode__() |
| 24 | + |
| 25 | + def _showfields_get_content(self, field_name, field_type=type(None)): |
| 26 | + "helper for __unicode__" |
| 27 | + content = getattr(self, field_name) |
| 28 | + if self.polymorphic_showfield_old_format: |
| 29 | + out = ': ' |
| 30 | + else: |
| 31 | + out = ' ' |
| 32 | + if issubclass(field_type, models.ForeignKey): |
| 33 | + if content is None: |
| 34 | + out += 'None' |
| 35 | + else: |
| 36 | + out += content.__class__.__name__ |
| 37 | + elif issubclass(field_type, models.ManyToManyField): |
| 38 | + out += '%d' % content.count() |
| 39 | + elif isinstance(content, six.integer_types): |
| 40 | + out += str(content) |
| 41 | + elif content is None: |
| 42 | + out += 'None' |
| 43 | + else: |
| 44 | + txt = str(content) |
| 45 | + if len(txt) > self.polymorphic_showfield_max_field_width: |
| 46 | + txt = txt[:self.polymorphic_showfield_max_field_width - 2] + '..' |
| 47 | + out += '"' + txt + '"' |
| 48 | + return out |
| 49 | + |
| 50 | + def _showfields_add_regular_fields(self, parts): |
| 51 | + "helper for __unicode__" |
| 52 | + done_fields = set() |
| 53 | + for field in self._meta.fields + self._meta.many_to_many: |
| 54 | + if field.name in self.polymorphic_internal_model_fields or '_ptr' in field.name: |
| 55 | + continue |
| 56 | + if field.name in done_fields: |
| 57 | + continue # work around django diamond inheritance problem |
| 58 | + done_fields.add(field.name) |
| 59 | + |
| 60 | + out = field.name |
| 61 | + |
| 62 | + # if this is the standard primary key named "id", print it as we did with older versions of django_polymorphic |
| 63 | + if field.primary_key and field.name == 'id' and type(field) == models.AutoField: |
| 64 | + out += ' ' + str(getattr(self, field.name)) |
| 65 | + |
| 66 | + # otherwise, display it just like all other fields (with correct type, shortened content etc.) |
| 67 | + else: |
| 68 | + if self.polymorphic_showfield_type: |
| 69 | + out += ' (' + type(field).__name__ |
| 70 | + if field.primary_key: |
| 71 | + out += '/pk' |
| 72 | + out += ')' |
| 73 | + |
| 74 | + if self.polymorphic_showfield_content: |
| 75 | + out += self._showfields_get_content(field.name, type(field)) |
| 76 | + |
| 77 | + parts.append((False, out, ',')) |
| 78 | + |
| 79 | + def _showfields_add_dynamic_fields(self, field_list, title, parts): |
| 80 | + "helper for __unicode__" |
| 81 | + parts.append((True, '- ' + title, ':')) |
| 82 | + for field_name in field_list: |
| 83 | + out = field_name |
| 84 | + content = getattr(self, field_name) |
| 85 | + if self.polymorphic_showfield_type: |
| 86 | + out += ' (' + type(content).__name__ + ')' |
| 87 | + if self.polymorphic_showfield_content: |
| 88 | + out += self._showfields_get_content(field_name) |
| 89 | + |
| 90 | + parts.append((False, out, ',')) |
| 91 | + |
| 92 | + def __unicode__(self): |
| 93 | + # create list ("parts") containing one tuple for each title/field: |
| 94 | + # ( bool: new section , item-text , separator to use after item ) |
| 95 | + |
| 96 | + # start with model name |
| 97 | + parts = [(True, self.__class__.__name__, ':')] |
| 98 | + |
| 99 | + # add all regular fields |
| 100 | + self._showfields_add_regular_fields(parts) |
| 101 | + |
| 102 | + # add annotate fields |
| 103 | + if hasattr(self, 'polymorphic_annotate_names'): |
| 104 | + self._showfields_add_dynamic_fields(self.polymorphic_annotate_names, 'Ann', parts) |
| 105 | + |
| 106 | + # add extra() select fields |
| 107 | + if hasattr(self, 'polymorphic_extra_select_names'): |
| 108 | + self._showfields_add_dynamic_fields(self.polymorphic_extra_select_names, 'Extra', parts) |
| 109 | + |
| 110 | + # format result |
| 111 | + |
| 112 | + indent = len(self.__class__.__name__) + 5 |
| 113 | + indentstr = ''.rjust(indent) |
| 114 | + out = '' |
| 115 | + xpos = 0 |
| 116 | + possible_line_break_pos = None |
| 117 | + |
| 118 | + for i in range(len(parts)): |
| 119 | + new_section, p, separator = parts[i] |
| 120 | + final = (i == len(parts) - 1) |
| 121 | + if not final: |
| 122 | + next_new_section, _, _ = parts[i + 1] |
| 123 | + |
| 124 | + if (self.polymorphic_showfield_max_line_width |
| 125 | + and xpos + len(p) > self.polymorphic_showfield_max_line_width |
| 126 | + and possible_line_break_pos != None): |
| 127 | + rest = out[possible_line_break_pos:] |
| 128 | + out = out[:possible_line_break_pos] |
| 129 | + out += '\n' + indentstr + rest |
| 130 | + xpos = indent + len(rest) |
| 131 | + |
| 132 | + out += p |
| 133 | + xpos += len(p) |
| 134 | + |
| 135 | + if not final: |
| 136 | + if not next_new_section: |
| 137 | + out += separator |
| 138 | + xpos += len(separator) |
| 139 | + out += ' ' |
| 140 | + xpos += 1 |
| 141 | + |
| 142 | + if not new_section: |
| 143 | + possible_line_break_pos = len(out) |
| 144 | + |
| 145 | + return '<' + out + '>' |
| 146 | + |
| 147 | + |
| 148 | +class ShowFieldType(ShowFieldBase): |
| 149 | + """ model mixin that shows the object's class and it's field types """ |
| 150 | + polymorphic_showfield_type = True |
| 151 | + |
| 152 | + |
| 153 | +class ShowFieldContent(ShowFieldBase): |
| 154 | + """ model mixin that shows the object's class, it's fields and field contents """ |
| 155 | + polymorphic_showfield_content = True |
| 156 | + |
| 157 | + |
| 158 | +class ShowFieldTypeAndContent(ShowFieldBase): |
| 159 | + """ model mixin, like ShowFieldContent, but also show field types """ |
| 160 | + polymorphic_showfield_type = True |
| 161 | + polymorphic_showfield_content = True |
| 162 | + |
| 163 | + |
| 164 | +# compatibility with old class names |
| 165 | +ShowFieldTypes = ShowFieldType |
| 166 | +ShowFields = ShowFieldContent |
| 167 | +ShowFieldsAndTypes = ShowFieldTypeAndContent |
0 commit comments