__init__.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. from django.core.exceptions import ValidationError
  2. from django.utils.module_loading import import_string
  3. from django.utils.translation import ugettext as _
  4. from misago.conf import settings
  5. from .basefields import *
  6. from .serializers import serialize_profilefields_data
  7. class ProfileFields(object):
  8. def __init__(self, fields_groups):
  9. self.is_loaded = False
  10. self.fields_groups = fields_groups
  11. self.fields_dict = {}
  12. def load(self):
  13. self.fields_dict = {}
  14. fieldnames = {}
  15. for group in self.fields_groups:
  16. for field_path in group['fields']:
  17. field = import_string(field_path)
  18. field._field_path = field_path
  19. if field_path in self.fields_dict:
  20. raise ValueError(
  21. "{} profile field has been specified twice".format(field._field_path)
  22. )
  23. if not getattr(field, 'fieldname', None):
  24. raise ValueError(
  25. "{} profile field has to specify fieldname attribute".format(
  26. field._field_path,
  27. )
  28. )
  29. if field.fieldname in fieldnames:
  30. raise ValueError(
  31. (
  32. '{} profile field defines fieldname "{}" '
  33. 'that is already in use by the {}'
  34. ).format(
  35. field._field_path,
  36. field.fieldname,
  37. fieldnames[field.fieldname],
  38. )
  39. )
  40. fieldnames[field.fieldname] = field_path
  41. self.fields_dict[field_path] = field()
  42. self.is_loaded = True
  43. def get_fields(self):
  44. if not self.is_loaded:
  45. self.load()
  46. return self.fields_dict.values()
  47. def get_fields_groups(self):
  48. if not self.is_loaded:
  49. self.load()
  50. groups = []
  51. for group in self.fields_groups:
  52. group_dict = {
  53. 'name': _(group['name']),
  54. 'fields': [],
  55. }
  56. for field_path in group['fields']:
  57. field = self.fields_dict[field_path]
  58. group_dict['fields'].append(field)
  59. if group_dict['fields']:
  60. groups.append(group_dict)
  61. return groups
  62. def add_fields_to_form(self, request, user, form):
  63. if not self.is_loaded:
  64. self.load()
  65. form._profile_fields = []
  66. for field in self.get_fields():
  67. if not field.is_editable(request, user):
  68. continue
  69. form._profile_fields.append(field.fieldname)
  70. form.fields[field.fieldname] = field.get_form_field(request, user)
  71. def add_fields_to_admin_form(self, request, user, form):
  72. self.add_fields_to_form(request, user, form)
  73. form._profile_fields_groups = []
  74. for group in self.fields_groups:
  75. group_dict = {
  76. 'name': _(group['name']),
  77. 'fields': [],
  78. }
  79. for field_path in group['fields']:
  80. field = self.fields_dict[field_path]
  81. if field.fieldname in form._profile_fields:
  82. group_dict['fields'].append(field.fieldname)
  83. if group_dict['fields']:
  84. form._profile_fields_groups.append(group_dict)
  85. def clean_form(self, request, user, form, cleaned_data):
  86. for field in self.get_fields():
  87. if field.fieldname not in cleaned_data:
  88. continue
  89. try:
  90. cleaned_data[field.fieldname] = field.clean(
  91. request, user, cleaned_data[field.fieldname])
  92. except ValidationError as e:
  93. form.add_error(field.fieldname, e)
  94. return cleaned_data
  95. def update_user_profile_fields(self, user, form):
  96. cleaned_profile_fields = {}
  97. for fieldname in form._profile_fields:
  98. if fieldname in form.cleaned_data:
  99. cleaned_profile_fields[fieldname] = form.cleaned_data[fieldname]
  100. user.profile_fields = cleaned_profile_fields
  101. def search_users(self, criteria, queryset):
  102. if not self.is_loaded:
  103. self.load()
  104. q_obj = None
  105. for field in self.fields_dict.values():
  106. q = field.search_users(criteria)
  107. if q:
  108. if q_obj:
  109. q_obj = q_obj | q
  110. else:
  111. q_obj = q
  112. if q_obj:
  113. return queryset.filter(q_obj)
  114. return queryset
  115. profilefields = ProfileFields(settings.MISAGO_PROFILE_FIELDS)