Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

showfields.py 5.9KB

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