basefields.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. from django import forms
  2. from django.db.models import Q
  3. from django.utils import html
  4. from misago.core.utils import format_plaintext_for_html
  5. __all__ = [
  6. "ProfileField",
  7. "TextProfileField",
  8. "UrlProfileField",
  9. "TextareaProfileField",
  10. "ChoiceProfileField",
  11. ]
  12. class ProfileField(object):
  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, "")
  47. if not self.readonly and not len(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():
  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():
  85. if key == value:
  86. return {"text": str(name)}
  87. return None
  88. def search_users(self, criteria):
  89. """custom search implementation for choice fields"""
  90. q_obj = Q(**{"profile_fields__%s__contains" % self.fieldname: criteria})
  91. for key, choice in self.get_choices():
  92. if key and criteria.lower() in str(choice).lower():
  93. q_obj = q_obj | Q(**{"profile_fields__%s" % self.fieldname: key})
  94. return q_obj
  95. class TextProfileField(ProfileField):
  96. def get_form_field(self, request, user):
  97. return forms.CharField(
  98. label=self.get_label(user),
  99. help_text=self.get_help_text(user),
  100. initial=user.profile_fields.get(self.fieldname),
  101. max_length=250,
  102. disabled=self.readonly,
  103. required=False,
  104. )
  105. def get_input_json(self, request, user):
  106. return {"type": "text"}
  107. class TextareaProfileField(ProfileField):
  108. def get_form_field(self, request, user):
  109. return forms.CharField(
  110. label=self.get_label(user),
  111. help_text=self.get_help_text(user),
  112. initial=user.profile_fields.get(self.fieldname),
  113. max_length=500,
  114. widget=forms.Textarea(attrs={"rows": 4}),
  115. disabled=self.readonly,
  116. required=False,
  117. )
  118. def get_input_json(self, request, user):
  119. return {"type": "textarea"}
  120. def get_value_display_data(self, request, user, value):
  121. return {"html": html.linebreaks(html.escape(value))}
  122. class UrlifiedTextareaProfileField(TextareaProfileField):
  123. def get_value_display_data(self, request, user, value):
  124. return {"html": format_plaintext_for_html(value)}
  125. class UrlProfileField(TextProfileField):
  126. def get_form_field(self, request, user):
  127. return forms.URLField(
  128. label=self.get_label(user),
  129. help_text=self.get_help_text(user),
  130. initial=user.profile_fields.get(self.fieldname),
  131. max_length=250,
  132. disabled=self.readonly,
  133. required=False,
  134. )
  135. def get_value_display_data(self, request, user, value):
  136. return {"text": value, "url": value}