diff options
| author | Tom Christie | 2012-10-22 13:29:18 -0700 | 
|---|---|---|
| committer | Tom Christie | 2012-10-22 13:29:18 -0700 | 
| commit | b7d11cbc57db2155a4436599d65bbc307adbb2dd (patch) | |
| tree | 8f6754b2d95b079d5b8c178fb52bcf330b1f3461 | |
| parent | aba0172f5c988af145113678fe3d4f411111d4ff (diff) | |
| parent | d1e05ea8d4b5d7f94bde9a574196505aa823a6ff (diff) | |
| download | django-rest-framework-b7d11cbc57db2155a4436599d65bbc307adbb2dd.tar.bz2 | |
Merge pull request #312 from markotibold/BrowsableAPIRenderer
WIP on #310
| -rw-r--r-- | rest_framework/renderers.py | 54 | 
1 files changed, 30 insertions, 24 deletions
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index b2dbffd2..c64fb517 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -224,11 +224,9 @@ class BrowsableAPIRenderer(BaseRenderer):          return content -    def get_form(self, view, method, request): +    def show_form_for_method(self, view, method, request):          """ -        Get a form, possibly bound to either the input or output data. -        In the absence on of the Resource having an associated form then -        provide a form that can be used to submit arbitrary content. +        Returns True if a form should be shown for this method.          """          if not method in view.allowed_methods:              return  # Not a valid method @@ -242,20 +240,9 @@ class BrowsableAPIRenderer(BaseRenderer):                  return  # Don't have permission          except:              return  # Don't have permission and exception explicitly raise +        return True -        if method == 'DELETE' or method == 'OPTIONS': -            return True  # Don't actually need to return a form - -        if (not getattr(view, 'get_serializer', None) or -            not parsers.FormParser in getattr(view, 'parser_classes')): -            media_types = [parser.media_type for parser in view.parser_classes] -            return self.get_generic_content_form(media_types) - -        ##### -        # TODO: This is a little bit of a hack.  Actually we'd like to remove -        #       this and just render serializer fields to html directly. - -        #  We need to map our Fields to Django's Fields. +    def serializer_to_form_fields(self, serializer):          field_mapping = {              serializers.FloatField: forms.FloatField,              serializers.IntegerField: forms.IntegerField, @@ -268,13 +255,7 @@ class BrowsableAPIRenderer(BaseRenderer):              serializers.ManyPrimaryKeyRelatedField: forms.ModelMultipleChoiceField          } -        # Creating an on the fly form see: http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python          fields = {} -        obj, data = None, None -        if getattr(view, 'object', None): -            obj = view.object - -        serializer = view.get_serializer(instance=obj)          for k, v in serializer.get_fields(True).items():              if getattr(v, 'readonly', True):                  continue @@ -306,9 +287,34 @@ class BrowsableAPIRenderer(BaseRenderer):                  fields[k] = field_mapping[v.__class__](**kwargs)              except KeyError:                  fields[k] = forms.CharField(**kwargs) +        return fields + +    def get_form(self, view, method, request): +        """ +        Get a form, possibly bound to either the input or output data. +        In the absence on of the Resource having an associated form then +        provide a form that can be used to submit arbitrary content. +        """ +        if not self.show_form_for_method(view, method, request): +            return + +        if method == 'DELETE' or method == 'OPTIONS': +            return True  # Don't actually need to return a form + +        if not getattr(view, 'get_serializer', None) or not parsers.FormParser in view.parser_classes: +            media_types = [parser.media_type for parser in view.parser_classes] +            return self.get_generic_content_form(media_types) + +        # Creating an on the fly form see: http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python +        obj, data = None, None +        if getattr(view, 'object', None): +            obj = view.object + +        serializer = view.get_serializer(instance=obj) +        fields = self.serializer_to_form_fields(serializer)          OnTheFlyForm = type("OnTheFlyForm", (forms.Form,), fields) -        if obj and not view.request.method == 'DELETE':  # Don't fill in the form when the object is deleted +        if obj:              data = serializer.data          form_instance = OnTheFlyForm(data)          return form_instance  | 
