basefields.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. from django import forms
  2. from django.db.models import Q
  3. from django.utils import html
  4. from ...core.utils import format_plaintext_for_html
  5. __all__ = [
  6. "ProfileField",
  7. "TextProfileField",
  8. "UrlProfileField",
  9. "TextareaProfileField",
  10. "ChoiceProfileField",
  11. ]
  12. class ProfileField:
  13. """
  14. Basic profile field
  15. """
  16. fieldname = None
  17. label = None
  18. help_text = None
  19. readonly = False
  20. def is_editable(self, request, user):
  21. return not self.readonly
  22. def get_label(self, user):
  23. if not self.label:
  24. raise NotImplementedError(
  25. "profile field class has to define label "
  26. "attribute or get_label(user) method"
  27. )
  28. return self.label
  29. def get_help_text(self, user):
  30. return self.help_text
  31. def get_form_field(self, request, user):
  32. return None
  33. def get_form_field_json(self, request, user):
  34. return {
  35. "fieldname": self.fieldname,
  36. "label": self.get_label(user),
  37. "help_text": self.get_help_text(user),
  38. "initial": user.profile_fields.get(self.fieldname, ""),
  39. "input": self.get_input_json(request, user),
  40. }
  41. def get_input_json(self, request, user):
  42. return None
  43. def clean(self, request, user, data):
  44. return data
  45. def get_display_data(self, request, user):
  46. value = user.profile_fields.get(self.fieldname, "").strip()
  47. if not self.readonly and not value:
  48. return None
  49. data = self.get_value_display_data(request, user, value)
  50. if not data:
  51. return None
  52. data.update({"fieldname": self.fieldname, "name": str(self.get_label(user))})
  53. return data
  54. def get_value_display_data(self, request, user, value):
  55. return {"text": value}
  56. def search_users(self, criteria):
  57. if self.readonly:
  58. return None
  59. return Q(**{"profile_fields__%s__contains" % self.fieldname: criteria})
  60. class ChoiceProfileField(ProfileField):
  61. choices = None
  62. def get_choices(self, user=None):
  63. if not self.choices:
  64. raise NotImplementedError(
  65. "profile field ChoiceProfileField has to define "
  66. "choices attribute or get_choices(user) method"
  67. )
  68. return self.choices
  69. def get_form_field(self, request, user):
  70. return forms.ChoiceField(
  71. label=self.get_label(user),
  72. help_text=self.get_help_text(user),
  73. initial=user.profile_fields.get(self.fieldname),
  74. choices=self.get_choices(user),
  75. disabled=self.readonly,
  76. required=False,
  77. )
  78. def get_input_json(self, request, user):
  79. choices = []
  80. for key, choice in self.get_choices(): # pylint: disable=not-an-iterable
  81. choices.append({"value": key, "label": choice})
  82. return {"type": "select", "choices": choices}
  83. def get_value_display_data(self, request, user, value):
  84. for key, name in self.get_choices(): # pylint: disable=not-an-iterable
  85. if key == value:
  86. return {"text": str(name)}
  87. def search_users(self, criteria):
  88. """custom search implementation for choice fields"""
  89. q_obj = Q(**{"profile_fields__%s__contains" % self.fieldname: criteria})
  90. for key, choice in self.get_choices(): # pylint: disable=not-an-iterable
  91. if key and criteria.lower() in str(choice).lower():
  92. q_obj = q_obj | Q(**{"profile_fields__%s" % self.fieldname: key})
  93. return q_obj
  94. class TextProfileField(ProfileField):
  95. def get_form_field(self, request, user):
  96. return forms.CharField(
  97. label=self.get_label(user),
  98. help_text=self.get_help_text(user),
  99. initial=user.profile_fields.get(self.fieldname),
  100. max_length=250,
  101. disabled=self.readonly,
  102. required=False,
  103. )
  104. def get_input_json(self, request, user):
  105. return {"type": "text"}
  106. class TextareaProfileField(ProfileField):
  107. def get_form_field(self, request, user):
  108. return forms.CharField(
  109. label=self.get_label(user),
  110. help_text=self.get_help_text(user),
  111. initial=user.profile_fields.get(self.fieldname),
  112. max_length=500,
  113. widget=forms.Textarea(attrs={"rows": 4}),
  114. disabled=self.readonly,
  115. required=False,
  116. )
  117. def get_input_json(self, request, user):
  118. return {"type": "textarea"}
  119. def get_value_display_data(self, request, user, value):
  120. return {"html": html.linebreaks(html.escape(value))}
  121. class UrlifiedTextareaProfileField(TextareaProfileField):
  122. def get_value_display_data(self, request, user, value):
  123. return {"html": format_plaintext_for_html(value)}
  124. class UrlProfileField(TextProfileField):
  125. def get_form_field(self, request, user):
  126. return forms.URLField(
  127. label=self.get_label(user),
  128. help_text=self.get_help_text(user),
  129. initial=user.profile_fields.get(self.fieldname),
  130. max_length=250,
  131. disabled=self.readonly,
  132. required=False,
  133. )
  134. def get_value_display_data(self, request, user, value):
  135. return {"text": value, "url": value}