diff options
| author | Tom Christie | 2013-08-23 16:10:20 +0100 | 
|---|---|---|
| committer | Tom Christie | 2013-08-23 16:10:20 +0100 | 
| commit | 10d386ec6a4822402b5ffea46bdd9e7d72db519b (patch) | |
| tree | 80ef9f700c1ee8e2bdb5c769edabb432bb763329 /rest_framework/renderers.py | |
| parent | b72a99fef2c84428240425ed42b1a0b1198631b1 (diff) | |
| download | django-rest-framework-10d386ec6a4822402b5ffea46bdd9e7d72db519b.tar.bz2 | |
Cleanup and dealing with empty form data.
Diffstat (limited to 'rest_framework/renderers.py')
| -rw-r--r-- | rest_framework/renderers.py | 103 | 
1 files changed, 54 insertions, 49 deletions
| diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index a73b2d73..a8670546 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -319,52 +319,53 @@ class StaticHTMLRenderer(TemplateHTMLRenderer):  class HTMLFormRenderer(BaseRenderer):      template = 'rest_framework/form.html' -    def serializer_to_form_fields(self, serializer): +    def data_to_form_fields(self, data):          fields = {} -        for k, v in serializer.get_fields().items(): -            if getattr(v, 'read_only', True): +        for key, val in data.fields.items(): +            if getattr(val, 'read_only', True):                  continue              kwargs = {} -            kwargs['required'] = v.required +            kwargs['required'] = val.required              #if getattr(v, 'queryset', None):              #    kwargs['queryset'] = v.queryset -            if getattr(v, 'choices', None) is not None: -                kwargs['choices'] = v.choices +            if getattr(val, 'choices', None) is not None: +                kwargs['choices'] = val.choices -            if getattr(v, 'regex', None) is not None: -                kwargs['regex'] = v.regex +            if getattr(val, 'regex', None) is not None: +                kwargs['regex'] = val.regex -            if getattr(v, 'widget', None): -                widget = copy.deepcopy(v.widget) +            if getattr(val, 'widget', None): +                widget = copy.deepcopy(val.widget)                  kwargs['widget'] = widget -            if getattr(v, 'default', None) is not None: -                kwargs['initial'] = v.default +            if getattr(val, 'default', None) is not None: +                kwargs['initial'] = val.default -            if getattr(v, 'label', None) is not None: -                kwargs['label'] = v.label +            if getattr(val, 'label', None) is not None: +                kwargs['label'] = val.label -            if getattr(v, 'help_text', None) is not None: -                kwargs['help_text'] = v.help_text +            if getattr(val, 'help_text', None) is not None: +                kwargs['help_text'] = val.help_text -            fields[k] = v.form_field_class(**kwargs) +            fields[key] = val.form_field_class(**kwargs)          return fields -    def render(self, serializer, obj, request): -        fields = self.serializer_to_form_fields(serializer) +    def render(self, data, accepted_media_type=None, renderer_context=None): +        self.renderer_context = renderer_context or {} +        request = renderer_context['request']          # Creating an on the fly form see:          # http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python -        OnTheFlyForm = type(str("OnTheFlyForm"), (forms.Form,), fields) -        data = (obj is not None) and serializer.data or None -        form_instance = OnTheFlyForm(data) +        fields = self.data_to_form_fields(data) +        DynamicForm = type(str('DynamicForm'), (forms.Form,), fields) +        data = None if data.empty else data          template = loader.get_template(self.template) -        context = RequestContext(request, {'form': form_instance}) +        context = RequestContext(request, {'form': DynamicForm(data)})          return template.render(context) @@ -377,6 +378,7 @@ class BrowsableAPIRenderer(BaseRenderer):      format = 'api'      template = 'rest_framework/api.html'      charset = 'utf-8' +    form_renderer_class = HTMLFormRenderer      def get_default_renderer(self, view):          """ @@ -424,19 +426,7 @@ class BrowsableAPIRenderer(BaseRenderer):              return False  # Doesn't have permissions          return True -    def _get_form(self, view, method, request): -        # We need to impersonate a request with the correct method, -        # so that eg. any dynamic get_serializer_class methods return the -        # correct form for each method. -        restore = view.request -        request = clone_request(request, method) -        view.request = request -        try: -            return self.get_form(view, method, request) -        finally: -            view.request = restore - -    def _get_raw_data_form(self, view, method, request, media_types): +    def _get_rendered_html_form(self, view, method, request):          # We need to impersonate a request with the correct method,          # so that eg. any dynamic get_serializer_class methods return the          # correct form for each method. @@ -444,15 +434,16 @@ class BrowsableAPIRenderer(BaseRenderer):          request = clone_request(request, method)          view.request = request          try: -            return self.get_raw_data_form(view, method, request, media_types) +            return self.get_rendered_html_form(view, method, request)          finally:              view.request = restore -    def get_form(self, view, method, request): +    def get_rendered_html_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. +        Return a string representing a rendered HTML form, possibly bound to +        either the input or output data. + +        In the absence of the View having an associated form then return None.          """          obj = getattr(view, 'object', None)          if not self.show_form_for_method(view, method, request, obj): @@ -465,7 +456,21 @@ class BrowsableAPIRenderer(BaseRenderer):              return          serializer = view.get_serializer(instance=obj) -        return HTMLFormRenderer().render(serializer, obj, request) +        data = serializer.data +        form_renderer = self.form_renderer_class() +        return form_renderer.render(data, self.accepted_media_type, self.renderer_context) + +    def _get_raw_data_form(self, view, method, request, media_types): +        # We need to impersonate a request with the correct method, +        # so that eg. any dynamic get_serializer_class methods return the +        # correct form for each method. +        restore = view.request +        request = clone_request(request, method) +        view.request = request +        try: +            return self.get_raw_data_form(view, method, request, media_types) +        finally: +            view.request = restore      def get_raw_data_form(self, view, method, request, media_types):          """ @@ -520,8 +525,8 @@ class BrowsableAPIRenderer(BaseRenderer):          """          Render the HTML for the browsable API representation.          """ -        accepted_media_type = accepted_media_type or '' -        renderer_context = renderer_context or {} +        self.accepted_media_type = accepted_media_type or '' +        self.renderer_context = renderer_context or {}          view = renderer_context['view']          request = renderer_context['request'] @@ -531,11 +536,11 @@ class BrowsableAPIRenderer(BaseRenderer):          renderer = self.get_default_renderer(view)          content = self.get_content(renderer, data, accepted_media_type, renderer_context) -        put_form = self._get_form(view, 'PUT', request) -        post_form = self._get_form(view, 'POST', request) -        patch_form = self._get_form(view, 'PATCH', request) -        delete_form = self._get_form(view, 'DELETE', request) -        options_form = self._get_form(view, 'OPTIONS', request) +        put_form = self._get_rendered_html_form(view, 'PUT', request) +        post_form = self._get_rendered_html_form(view, 'POST', request) +        patch_form = self._get_rendered_html_form(view, 'PATCH', request) +        delete_form = self._get_rendered_html_form(view, 'DELETE', request) +        options_form = self._get_rendered_html_form(view, 'OPTIONS', request)          raw_data_put_form = self._get_raw_data_form(view, 'PUT', request, media_types)          raw_data_post_form = self._get_raw_data_form(view, 'POST', request, media_types) | 
