mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-04-25 19:43:47 +03:00
Fix rendering of forms and add error rendering on HTML form
This commit is contained in:
parent
a14f1e8864
commit
8d4ba478cc
|
@ -419,6 +419,13 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
|
|
||||||
In the absence of the View having an associated form then return None.
|
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:
|
with override_method(view, request, method) as request:
|
||||||
obj = getattr(view, 'object', None)
|
obj = getattr(view, 'object', None)
|
||||||
if not self.show_form_for_method(view, method, request, obj):
|
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)):
|
or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)):
|
||||||
return
|
return
|
||||||
|
|
||||||
serializer = view.get_serializer(instance=obj)
|
serializer = view.get_serializer(instance=obj, data=data, files=files)
|
||||||
|
serializer.is_valid()
|
||||||
data = serializer.data
|
data = serializer.data
|
||||||
|
|
||||||
form_renderer = self.form_renderer_class()
|
form_renderer = self.form_renderer_class()
|
||||||
return form_renderer.render(data, self.accepted_media_type, self.renderer_context)
|
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)
|
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_put_form = self.get_raw_data_form(view, 'PUT', request)
|
||||||
raw_data_patch_form = self.get_raw_data_form(view, 'PATCH', 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
|
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),
|
'put_form': self.get_rendered_html_form(view, 'PUT', request),
|
||||||
'post_form': self.get_rendered_html_form(view, 'POST', 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),
|
'delete_form': self.get_rendered_html_form(view, 'DELETE', request),
|
||||||
'options_form': self.get_rendered_html_form(view, 'OPTIONS', request),
|
'options_form': self.get_rendered_html_form(view, 'OPTIONS', request),
|
||||||
|
|
||||||
'raw_data_put_form': raw_data_put_form,
|
'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_patch_form': raw_data_patch_form,
|
||||||
'raw_data_put_or_patch_form': raw_data_put_or_patch_form,
|
'raw_data_put_or_patch_form': raw_data_put_or_patch_form,
|
||||||
|
|
||||||
|
|
|
@ -308,24 +308,14 @@ class BaseSerializer(WritableField):
|
||||||
"""
|
"""
|
||||||
ret = self._dict_class()
|
ret = self._dict_class()
|
||||||
ret.fields = self._dict_class()
|
ret.fields = self._dict_class()
|
||||||
ret.empty = obj is None
|
|
||||||
|
|
||||||
for field_name, field in self.fields.items():
|
for field_name, field in self.fields.items():
|
||||||
field.initialize(parent=self, field_name=field_name)
|
field.initialize(parent=self, field_name=field_name)
|
||||||
key = self.get_field_key(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)
|
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)
|
|
||||||
|
|
||||||
ret[key] = value
|
ret[key] = value
|
||||||
ret.fields[key] = field
|
ret.fields[key] = self.augment_field(field, field_name, key, value)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def from_native(self, data, files):
|
def from_native(self, data, files):
|
||||||
|
@ -333,6 +323,7 @@ class BaseSerializer(WritableField):
|
||||||
Deserialize primitives -> objects.
|
Deserialize primitives -> objects.
|
||||||
"""
|
"""
|
||||||
self._errors = {}
|
self._errors = {}
|
||||||
|
|
||||||
if data is not None or files is not None:
|
if data is not None or files is not None:
|
||||||
attrs = self.restore_fields(data, files)
|
attrs = self.restore_fields(data, files)
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
|
@ -343,6 +334,15 @@ class BaseSerializer(WritableField):
|
||||||
if not self._errors:
|
if not self._errors:
|
||||||
return self.restore_object(attrs, instance=getattr(self, 'object', None))
|
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):
|
def field_to_native(self, obj, field_name):
|
||||||
"""
|
"""
|
||||||
Override default so that the serializer can be used as a nested field
|
Override default so that the serializer can be used as a nested field
|
||||||
|
|
|
@ -151,7 +151,7 @@
|
||||||
{% with form=raw_data_post_form %}
|
{% with form=raw_data_post_form %}
|
||||||
<form action="{{ request.get_full_path }}" method="POST" class="form-horizontal">
|
<form action="{{ request.get_full_path }}" method="POST" class="form-horizontal">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
{% include "rest_framework/form.html" %}
|
{% include "rest_framework/raw_data_form.html" %}
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button class="btn btn-primary" title="Make a POST request on the {{ name }} resource">POST</button>
|
<button class="btn btn-primary" title="Make a POST request on the {{ name }} resource">POST</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -188,7 +188,7 @@
|
||||||
{% with form=raw_data_put_or_patch_form %}
|
{% with form=raw_data_put_or_patch_form %}
|
||||||
<form action="{{ request.get_full_path }}" method="POST" class="form-horizontal">
|
<form action="{{ request.get_full_path }}" method="POST" class="form-horizontal">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
{% include "rest_framework/form.html" %}
|
{% include "rest_framework/raw_data_form.html" %}
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
{% if raw_data_put_form %}
|
{% 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>
|
<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>
|
||||||
|
|
12
rest_framework/templates/rest_framework/raw_data_form.html
Normal file
12
rest_framework/templates/rest_framework/raw_data_form.html
Normal file
|
@ -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 %}
|
Loading…
Reference in New Issue
Block a user