diff options
| author | Tom Christie | 2013-10-02 16:13:34 +0100 |
|---|---|---|
| committer | Tom Christie | 2013-10-02 16:13:34 +0100 |
| commit | 8d4ba478cc5725b4de6ab86b4825b1ea94cb4c7b (patch) | |
| tree | 75187b1e1d5bd77dd4f137b467da5ce7a5b09603 /rest_framework | |
| parent | a14f1e886402b8d0f742fdbb912b03a4004e1735 (diff) | |
| download | django-rest-framework-8d4ba478cc5725b4de6ab86b4825b1ea94cb4c7b.tar.bz2 | |
Fix rendering of forms and add error rendering on HTML form
Diffstat (limited to 'rest_framework')
| -rw-r--r-- | rest_framework/renderers.py | 16 | ||||
| -rw-r--r-- | rest_framework/serializers.py | 26 | ||||
| -rw-r--r-- | rest_framework/templates/rest_framework/base.html | 4 | ||||
| -rw-r--r-- | rest_framework/templates/rest_framework/raw_data_form.html | 12 |
4 files changed, 39 insertions, 19 deletions
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 0e17edaf..fe4f43d4 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -419,6 +419,13 @@ class BrowsableAPIRenderer(BaseRenderer): In the absence of the View having an associated form then return None. """ + if request.method == method: + data = request.DATA + files = request.FILES + else: + data = None + files = None + with override_method(view, request, method) as request: obj = getattr(view, 'object', None) if not self.show_form_for_method(view, method, request, obj): @@ -431,9 +438,10 @@ class BrowsableAPIRenderer(BaseRenderer): or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)): return - serializer = view.get_serializer(instance=obj) - + serializer = view.get_serializer(instance=obj, data=data, files=files) + serializer.is_valid() data = serializer.data + form_renderer = self.form_renderer_class() return form_renderer.render(data, self.accepted_media_type, self.renderer_context) @@ -525,6 +533,7 @@ class BrowsableAPIRenderer(BaseRenderer): renderer = self.get_default_renderer(view) + raw_data_post_form = self.get_raw_data_form(view, 'POST', request) raw_data_put_form = self.get_raw_data_form(view, 'PUT', request) raw_data_patch_form = self.get_raw_data_form(view, 'PATCH', request) raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form @@ -543,12 +552,11 @@ class BrowsableAPIRenderer(BaseRenderer): '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': raw_data_put_form, - 'raw_data_post_form': self.get_raw_data_form(view, 'POST', request), + 'raw_data_post_form': raw_data_post_form, 'raw_data_patch_form': raw_data_patch_form, 'raw_data_put_or_patch_form': raw_data_put_or_patch_form, diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 206a8123..bc9f73d1 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -308,24 +308,14 @@ class BaseSerializer(WritableField): """ ret = self._dict_class() ret.fields = self._dict_class() - ret.empty = obj is None for field_name, field in self.fields.items(): field.initialize(parent=self, field_name=field_name) key = self.get_field_key(field_name) - if self._errors: - value = self.init_data.get(field_name) - else: - value = field.field_to_native(obj, field_name) - - field._errors = self._errors.get(key) if self._errors else None - field._name = field_name - field._value = value - if not field.label: - field.label = pretty_name(key) - + value = field.field_to_native(obj, field_name) ret[key] = value - ret.fields[key] = field + ret.fields[key] = self.augment_field(field, field_name, key, value) + return ret def from_native(self, data, files): @@ -333,6 +323,7 @@ class BaseSerializer(WritableField): Deserialize primitives -> objects. """ self._errors = {} + if data is not None or files is not None: attrs = self.restore_fields(data, files) if attrs is not None: @@ -343,6 +334,15 @@ class BaseSerializer(WritableField): if not self._errors: return self.restore_object(attrs, instance=getattr(self, 'object', None)) + def augment_field(self, field, field_name, key, value): + # This horrible stuff is to manage serializers rendering to HTML + field._errors = self._errors.get(key) if self._errors else None + field._name = field_name + field._value = self.init_data.get(key) if self._errors and self.init_data else value + if not field.label: + field.label = pretty_name(key) + return field + def field_to_native(self, obj, field_name): """ Override default so that the serializer can be used as a nested field diff --git a/rest_framework/templates/rest_framework/base.html b/rest_framework/templates/rest_framework/base.html index 2776d550..33be36db 100644 --- a/rest_framework/templates/rest_framework/base.html +++ b/rest_framework/templates/rest_framework/base.html @@ -151,7 +151,7 @@ {% with form=raw_data_post_form %} <form action="{{ request.get_full_path }}" method="POST" class="form-horizontal"> <fieldset> - {% include "rest_framework/form.html" %} + {% include "rest_framework/raw_data_form.html" %} <div class="form-actions"> <button class="btn btn-primary" title="Make a POST request on the {{ name }} resource">POST</button> </div> @@ -188,7 +188,7 @@ {% with form=raw_data_put_or_patch_form %} <form action="{{ request.get_full_path }}" method="POST" class="form-horizontal"> <fieldset> - {% include "rest_framework/form.html" %} + {% include "rest_framework/raw_data_form.html" %} <div class="form-actions"> {% if raw_data_put_form %} <button class="btn btn-primary js-tooltip" name="{{ api_settings.FORM_METHOD_OVERRIDE }}" value="PUT" title="Make a PUT request on the {{ name }} resource">PUT</button> diff --git a/rest_framework/templates/rest_framework/raw_data_form.html b/rest_framework/templates/rest_framework/raw_data_form.html new file mode 100644 index 00000000..075279f7 --- /dev/null +++ b/rest_framework/templates/rest_framework/raw_data_form.html @@ -0,0 +1,12 @@ +{% load rest_framework %} +{% csrf_token %} +{{ form.non_field_errors }} +{% for field in form %} + <div class="control-group"> + {{ field.label_tag|add_class:"control-label" }} + <div class="controls"> + {{ field }} + <span class="help-block">{{ field.help_text }}</span> + </div> + </div> +{% endfor %} |
