basefields.py 5.5 KB

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