123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- import re
-
- from django.db import models
-
- RE_DEFERRED = re.compile("_Deferred_.*")
-
-
- class ShowFieldBase:
- """base class for the ShowField... model mixins, does the work"""
-
- # cause nicer multiline PolymorphicQuery output
- polymorphic_query_multiline_output = True
-
- polymorphic_showfield_type = False
- polymorphic_showfield_content = False
- polymorphic_showfield_deferred = False
-
- # these may be overridden by the user
- polymorphic_showfield_max_line_width = None
- polymorphic_showfield_max_field_width = 20
- polymorphic_showfield_old_format = False
-
- def __repr__(self):
- return self.__str__()
-
- def _showfields_get_content(self, field_name, field_type=type(None)):
- "helper for __unicode__"
- content = getattr(self, field_name)
- if self.polymorphic_showfield_old_format:
- out = ": "
- else:
- out = " "
- if issubclass(field_type, models.ForeignKey):
- if content is None:
- out += "None"
- else:
- out += content.__class__.__name__
- elif issubclass(field_type, models.ManyToManyField):
- out += "%d" % content.count()
- elif isinstance(content, int):
- out += str(content)
- elif content is None:
- out += "None"
- else:
- txt = str(content)
- if len(txt) > self.polymorphic_showfield_max_field_width:
- txt = txt[: self.polymorphic_showfield_max_field_width - 2] + ".."
- out += '"' + txt + '"'
- return out
-
- def _showfields_add_regular_fields(self, parts):
- "helper for __unicode__"
- done_fields = set()
- for field in self._meta.fields + self._meta.many_to_many:
- if field.name in self.polymorphic_internal_model_fields or "_ptr" in field.name:
- continue
- if field.name in done_fields:
- continue # work around django diamond inheritance problem
- done_fields.add(field.name)
-
- out = field.name
-
- # if this is the standard primary key named "id", print it as we did with older versions of django_polymorphic
- if field.primary_key and field.name == "id" and type(field) == models.AutoField:
- out += " " + str(getattr(self, field.name))
-
- # otherwise, display it just like all other fields (with correct type, shortened content etc.)
- else:
- if self.polymorphic_showfield_type:
- out += " (" + type(field).__name__
- if field.primary_key:
- out += "/pk"
- out += ")"
-
- if self.polymorphic_showfield_content:
- out += self._showfields_get_content(field.name, type(field))
-
- parts.append((False, out, ","))
-
- def _showfields_add_dynamic_fields(self, field_list, title, parts):
- "helper for __unicode__"
- parts.append((True, "- " + title, ":"))
- for field_name in field_list:
- out = field_name
- content = getattr(self, field_name)
- if self.polymorphic_showfield_type:
- out += " (" + type(content).__name__ + ")"
- if self.polymorphic_showfield_content:
- out += self._showfields_get_content(field_name)
-
- parts.append((False, out, ","))
-
- def __str__(self):
- # create list ("parts") containing one tuple for each title/field:
- # ( bool: new section , item-text , separator to use after item )
-
- # start with model name
- parts = [(True, RE_DEFERRED.sub("", self.__class__.__name__), ":")]
-
- # add all regular fields
- self._showfields_add_regular_fields(parts)
-
- # add annotate fields
- if hasattr(self, "polymorphic_annotate_names"):
- self._showfields_add_dynamic_fields(self.polymorphic_annotate_names, "Ann", parts)
-
- # add extra() select fields
- if hasattr(self, "polymorphic_extra_select_names"):
- self._showfields_add_dynamic_fields(
- self.polymorphic_extra_select_names, "Extra", parts
- )
-
- if self.polymorphic_showfield_deferred:
- fields = self.get_deferred_fields()
- if fields:
- parts.append((False, "deferred[{}]".format(",".join(sorted(fields))), ""))
-
- # format result
-
- indent = len(self.__class__.__name__) + 5
- indentstr = "".rjust(indent)
- out = ""
- xpos = 0
- possible_line_break_pos = None
-
- for i in range(len(parts)):
- new_section, p, separator = parts[i]
- final = i == len(parts) - 1
- if not final:
- next_new_section, _, _ = parts[i + 1]
-
- if (
- self.polymorphic_showfield_max_line_width
- and xpos + len(p) > self.polymorphic_showfield_max_line_width
- and possible_line_break_pos is not None
- ):
- rest = out[possible_line_break_pos:]
- out = out[:possible_line_break_pos]
- out += "\n" + indentstr + rest
- xpos = indent + len(rest)
-
- out += p
- xpos += len(p)
-
- if not final:
- if not next_new_section:
- out += separator
- xpos += len(separator)
- out += " "
- xpos += 1
-
- if not new_section:
- possible_line_break_pos = len(out)
-
- return "<" + out + ">"
-
-
- class ShowFieldType(ShowFieldBase):
- """model mixin that shows the object's class and it's field types"""
-
- polymorphic_showfield_type = True
-
-
- class ShowFieldContent(ShowFieldBase):
- """model mixin that shows the object's class, it's fields and field contents"""
-
- polymorphic_showfield_content = True
-
-
- class ShowFieldTypeAndContent(ShowFieldBase):
- """model mixin, like ShowFieldContent, but also show field types"""
-
- polymorphic_showfield_type = True
- polymorphic_showfield_content = True
|