Просмотр исходного кода

wip #865: documented more of the profile fields api

Rafał Pitoń 8 лет назад
Родитель
Сommit
b037e49bd4
2 измененных файлов с 141 добавлено и 7 удалено
  1. 140 2
      docs/ProfileFields.md
  2. 1 5
      misago/users/profilefields/basefields.py

+ 140 - 2
docs/ProfileFields.md

@@ -104,17 +104,155 @@ class TwitterHandleField(basefields.TextProfileField):
 ```
 
 
+### `readonly`
+
+Defining `readonly = True` on field will make it never editable. This is useful when you are defining profile fields that display different information about user but are never editable on their own.
+
+Example field that displays to moderators an IP address that user used to register account:
+
+```python
+class JoinIpField(basefields.TextProfileField):
+    fieldname = 'join_ip'
+    label = _("Join IP")
+    readonly = True
+
+    def get_value_display_data(self, request, user, value):
+        if not request.user.acl_cache.get('can_see_users_ips'):
+            return None
+
+        return {
+            'text': user.joined_from_ip
+        }
+```
+
+
+### `is_editable`
+
+The `is_editable` method allows you make field *conditionally* read-only.
+
+Below profile field will be only editable by profile field's moderators:
+
+```python
+class ModeratorDescriptionField(basefields.UrlifiedTextareaProfileField):
+    fieldname = 'moderatordescription'
+    label = _("Moderator description")
+
+    def is_editable(self, request, user):
+        return request.user.acl_cache.get('can_moderate_profile_details')
+```
+
+
 ### `get_form_field`
+
+The `get_form_field` method is called to obtain form field that is then added to user edit form, plugging the field to Django's form handling mechanics.
+
+This method is used in two places:
+
+1. to add field to edit user form in admin control panel.
+2. to add field to edit user details form used behind the courtain by Misago to clean and validate user details sent to API from "edit details" form in user options and on user profile pages.
+
+This field uses `get_form_field` to specify `URLField` as field that should be used to edit its value:
+
+```python
+class WebsiteField(basefields.UrlProfileField):
+    fieldname = 'website'
+    label = _("Website")
+
+    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,
+        )
+```
+
+Notice that the fact that this field is hidden from users outside of admin control panel means that you may use it to specify admin-oriented `label` and `help_text` within it, and use `label` and `help_text` props documented ealier for user-facing UI.
+
+Also take a note that while its not necessary, its good practice for all profile fields to be optional, and thus specify `required=False` on field returned by `get_form_field`.
+
+
 ### `get_form_field_json`
+
+This method is called to obtain the JSON describing how to build edit field in JavaScript UI. Because default implementation provided by the `ProfileField` is versalite enough for great majority of use cases, its unlikely that you'll ever want to write custom implementation for your fields, instead limiting yourself to editing the `get_input_json` exclusively.
+
+```python
+class FullNameField(basefields.TextProfileField):
+    fieldname = 'fullname'
+    label = _("Full name")
+
+    def get_form_field_json(self, request, user):
+        # default implementation inherited from ProfileField
+        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),
+        }
+```
+
+Very much alike the `get_form_field` documented ealier, because this method is origin of truth for details edit forms in user-facing UI, you may modify it to customize field's label and help text.
+
+
 ### `get_input_json`
+
+This method is called to obtain the JSON describing field input to create in end-user facing forms.
+
+It supports either of those values:
+
+```python
+# this field will have text input to edit it
+def get_input_json(self, request, user):
+    return {
+        'type': 'text',
+    }
+
+# this field will have textarea to edit it
+def get_input_json(self, request, user):
+    return {
+        'type': 'textarea',
+    }
+
+# this field will have select to edit it
+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': [
+            {
+                'value': '',
+                'label': _("Not specified"),
+            },
+            {
+                'value': 'female',
+                'label': _("Female"),
+            },
+            {
+                'value': 'male',
+                'label': _("Male"),
+            },
+        ],
+    }
+```
+
+Misago comes with convenience base classes for popular input types like text, textarea or select, that are documented further into this document.
+
+
 ### `clean`
 ### `get_display_data`
 ### `get_value_display_data`
 ### `search_users`
 
 
-## Read only profile fields
-
 ## Base fields
 
 ## Default fields

+ 1 - 5
misago/users/profilefields/basefields.py

@@ -42,16 +42,12 @@ class ProfileField(object):
         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,
+            'input': self.get_input_json(request, user),
         }
 
     def get_input_json(self, request, user):