basefields.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. __all__ = [
  7. 'ProfileField',
  8. 'TextProfileField',
  9. 'UrlProfileField',
  10. 'TextareaProfileField',
  11. 'ChoiceProfileField',
  12. ]
  13. class ProfileField(object):
  14. """
  15. Basic profile field
  16. """
  17. fieldname = None
  18. label = None
  19. help_text = None
  20. readonly = False
  21. def get_label(self, user):
  22. if not self.label:
  23. raise NotImplementedError(
  24. "profile field class has to define label "
  25. "attribute or get_label(user) method"
  26. )
  27. return self.label
  28. def get_help_text(self, user):
  29. return self.help_text
  30. def get_admin_field(self, user):
  31. return None
  32. def clean_admin_form(self, form, data):
  33. return data
  34. def admin_update_profile_fields(self, user, cleaned_data):
  35. if self.readonly:
  36. return
  37. user.profile_fields[self.fieldname] = cleaned_data.get(self.fieldname)
  38. def admin_search(self, criteria, queryset):
  39. return Q(**{
  40. 'profile_fields__{}__contains'.format(self.fieldname): criteria
  41. })
  42. def get_data(self, request, user):
  43. field_data = user.profile_fields.get(self.fieldname, '')
  44. if not len(field_data):
  45. return None
  46. data = self.get_display_data(request, user, field_data)
  47. if not data:
  48. return None
  49. data['name'] = text_type(self.get_label(user))
  50. return data
  51. def get_display_data(self, request, user, data):
  52. return {
  53. 'text': data
  54. }
  55. def can_edit(self, request, user):
  56. return not self.readonly
  57. class ChoiceProfileField(ProfileField):
  58. choices = None
  59. def get_choices(self, user=None):
  60. if not self.choices:
  61. raise NotImplementedError(
  62. "profile field ChoiceProfileField has to define "
  63. "choices attribute or get_choices(user) method"
  64. )
  65. return self.choices
  66. def get_admin_field(self, user):
  67. return forms.ChoiceField(
  68. label=self.get_label(user),
  69. help_text=self.get_help_text(user),
  70. initial=user.profile_fields.get(self.fieldname),
  71. choices=self.get_choices(user),
  72. disabled=self.readonly,
  73. required=False,
  74. )
  75. def admin_search(self, criteria, queryset):
  76. """custom search implementation for choice fields"""
  77. q_obj = Q(**{
  78. 'profile_fields__{}__contains'.format(self.fieldname): criteria
  79. })
  80. for key, choice in self.get_choices():
  81. if key and criteria.lower() in text_type(choice).lower():
  82. q_obj = q_obj | Q(**{
  83. 'profile_fields__{}'.format(self.fieldname): key
  84. })
  85. return q_obj
  86. def get_display_data(self, request, user, data):
  87. for key, name in self.get_choices():
  88. if key == data:
  89. return {
  90. 'text': text_type(name),
  91. }
  92. return None
  93. class TextProfileField(ProfileField):
  94. def get_admin_field(self, user):
  95. return forms.CharField(
  96. label=self.get_label(user),
  97. help_text=self.get_help_text(user),
  98. initial=user.profile_fields.get(self.fieldname),
  99. max_length=250,
  100. disabled=self.readonly,
  101. required=False,
  102. )
  103. class TextareaProfileField(ProfileField):
  104. def get_admin_field(self, user):
  105. return forms.CharField(
  106. label=self.get_label(user),
  107. help_text=self.get_help_text(user),
  108. initial=user.profile_fields.get(self.fieldname),
  109. max_length=250,
  110. widget=forms.Textarea(
  111. attrs={'rows': 4},
  112. ),
  113. disabled=self.readonly,
  114. required=False,
  115. )
  116. def get_display_data(self, request, user, data):
  117. return {
  118. 'html': html.linebreaks(html.escape(data)),
  119. }
  120. class UrlifiedTextareaProfileField(TextareaProfileField):
  121. def get_display_data(self, request, user, data):
  122. return {
  123. 'html': format_plaintext_for_html(data),
  124. }
  125. class SlugProfileField(ProfileField):
  126. def get_admin_field(self, user):
  127. return forms.SlugField(
  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_display_data(self, request, user, data):
  136. return {
  137. 'text': data,
  138. 'url': data,
  139. }
  140. class UrlProfileField(ProfileField):
  141. def get_admin_field(self, user):
  142. return forms.URLField(
  143. label=self.get_label(user),
  144. help_text=self.get_help_text(user),
  145. initial=user.profile_fields.get(self.fieldname),
  146. max_length=250,
  147. disabled=self.readonly,
  148. required=False,
  149. )
  150. def get_display_data(self, request, user, data):
  151. return {
  152. 'text': data,
  153. 'url': data,
  154. }