from django import forms from django.db.models import Q from django.utils import html from ...core.utils import format_plaintext_for_html __all__ = [ "ProfileField", "TextProfileField", "UrlProfileField", "TextareaProfileField", "ChoiceProfileField", ] class ProfileField(object): """ Basic profile field """ fieldname = None label = None help_text = None readonly = False def is_editable(self, request, user): return not self.readonly def get_label(self, user): if not self.label: raise NotImplementedError( "profile field class has to define label " "attribute or get_label(user) method" ) return self.label def get_help_text(self, user): return self.help_text def get_form_field(self, request, user): return None def get_form_field_json(self, request, user): return { "fieldname": self.fieldname, "label": self.get_label(user), "help_text": self.get_help_text(user), "initial": user.profile_fields.get(self.fieldname, ""), "input": self.get_input_json(request, user), } def get_input_json(self, request, user): return None def clean(self, request, user, data): return data def get_display_data(self, request, user): value = user.profile_fields.get(self.fieldname, "") if not self.readonly and not len(value): return None data = self.get_value_display_data(request, user, value) if not data: return None data.update({"fieldname": self.fieldname, "name": str(self.get_label(user))}) return data def get_value_display_data(self, request, user, value): return {"text": value} def search_users(self, criteria): if self.readonly: return None return Q(**{"profile_fields__%s__contains" % self.fieldname: criteria}) class ChoiceProfileField(ProfileField): choices = None def get_choices(self, user=None): if not self.choices: raise NotImplementedError( "profile field ChoiceProfileField has to define " "choices attribute or get_choices(user) method" ) return self.choices def get_form_field(self, request, user): return forms.ChoiceField( label=self.get_label(user), help_text=self.get_help_text(user), initial=user.profile_fields.get(self.fieldname), choices=self.get_choices(user), disabled=self.readonly, required=False, ) def get_input_json(self, request, user): choices = [] for key, choice in self.get_choices(): choices.append({"value": key, "label": choice}) return {"type": "select", "choices": choices} def get_value_display_data(self, request, user, value): for key, name in self.get_choices(): if key == value: return {"text": str(name)} return None def search_users(self, criteria): """custom search implementation for choice fields""" q_obj = Q(**{"profile_fields__%s__contains" % self.fieldname: criteria}) for key, choice in self.get_choices(): if key and criteria.lower() in str(choice).lower(): q_obj = q_obj | Q(**{"profile_fields__%s" % self.fieldname: key}) return q_obj class TextProfileField(ProfileField): def get_form_field(self, request, user): return forms.CharField( label=self.get_label(user), help_text=self.get_help_text(user), initial=user.profile_fields.get(self.fieldname), max_length=250, disabled=self.readonly, required=False, ) def get_input_json(self, request, user): return {"type": "text"} class TextareaProfileField(ProfileField): def get_form_field(self, request, user): return forms.CharField( label=self.get_label(user), help_text=self.get_help_text(user), initial=user.profile_fields.get(self.fieldname), max_length=500, widget=forms.Textarea(attrs={"rows": 4}), disabled=self.readonly, required=False, ) def get_input_json(self, request, user): return {"type": "textarea"} def get_value_display_data(self, request, user, value): return {"html": html.linebreaks(html.escape(value))} class UrlifiedTextareaProfileField(TextareaProfileField): def get_value_display_data(self, request, user, value): return {"html": format_plaintext_for_html(value)} class UrlProfileField(TextProfileField): def get_form_field(self, request, user): return forms.URLField( label=self.get_label(user), help_text=self.get_help_text(user), initial=user.profile_fields.get(self.fieldname), max_length=250, disabled=self.readonly, required=False, ) def get_value_display_data(self, request, user, value): return {"text": value, "url": value}