from django import forms from django.db.models import Q from django.utils import html from django.utils.six import text_type from misago.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): input_json = self.get_input_json(request, user) if not input_json: return None return { 'fieldname': self.fieldname, 'label': self.get_label(user), 'help_text': self.get_help_text(user), 'initial': user.profile_fields.get(self.fieldname, ''), 'input': input_json, } 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': text_type(self.get_label(user)), }) return data def get_value_display_data(self, request, user, value): return { 'text': value } def search_users(self, criteria, queryset): return Q(**{ 'profile_fields__{}__contains'.format(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': text_type(name), } return None def search_users(self, criteria, queryset): """custom search implementation for choice fields""" q_obj = Q(**{ 'profile_fields__{}__contains'.format(self.fieldname): criteria }) for key, choice in self.get_choices(): if key and criteria.lower() in text_type(choice).lower(): q_obj = q_obj | Q(**{ 'profile_fields__{}'.format(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, }