mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-06-18 20:43:29 +03:00
First pass at HTMLFormRenderer
This commit is contained in:
parent
f54fc3a76b
commit
0966a2680b
|
@ -316,6 +316,59 @@ class StaticHTMLRenderer(TemplateHTMLRenderer):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLFormRenderer(BaseRenderer):
|
||||||
|
template = 'rest_framework/form.html'
|
||||||
|
|
||||||
|
def serializer_to_form_fields(self, serializer):
|
||||||
|
fields = {}
|
||||||
|
for k, v in serializer.get_fields().items():
|
||||||
|
if getattr(v, 'read_only', True):
|
||||||
|
continue
|
||||||
|
|
||||||
|
kwargs = {}
|
||||||
|
kwargs['required'] = v.required
|
||||||
|
|
||||||
|
#if getattr(v, 'queryset', None):
|
||||||
|
# kwargs['queryset'] = v.queryset
|
||||||
|
|
||||||
|
if getattr(v, 'choices', None) is not None:
|
||||||
|
kwargs['choices'] = v.choices
|
||||||
|
|
||||||
|
if getattr(v, 'regex', None) is not None:
|
||||||
|
kwargs['regex'] = v.regex
|
||||||
|
|
||||||
|
if getattr(v, 'widget', None):
|
||||||
|
widget = copy.deepcopy(v.widget)
|
||||||
|
kwargs['widget'] = widget
|
||||||
|
|
||||||
|
if getattr(v, 'default', None) is not None:
|
||||||
|
kwargs['initial'] = v.default
|
||||||
|
|
||||||
|
if getattr(v, 'label', None) is not None:
|
||||||
|
kwargs['label'] = v.label
|
||||||
|
|
||||||
|
if getattr(v, 'help_text', None) is not None:
|
||||||
|
kwargs['help_text'] = v.help_text
|
||||||
|
|
||||||
|
fields[k] = v.form_field_class(**kwargs)
|
||||||
|
|
||||||
|
return fields
|
||||||
|
|
||||||
|
def render(self, serializer, obj, request):
|
||||||
|
fields = self.serializer_to_form_fields(serializer)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
template = loader.get_template(self.template)
|
||||||
|
context = RequestContext(request, {'form': form_instance})
|
||||||
|
|
||||||
|
return template.render(context)
|
||||||
|
|
||||||
|
|
||||||
class BrowsableAPIRenderer(BaseRenderer):
|
class BrowsableAPIRenderer(BaseRenderer):
|
||||||
"""
|
"""
|
||||||
HTML renderer used to self-document the API.
|
HTML renderer used to self-document the API.
|
||||||
|
@ -371,41 +424,6 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
return False # Doesn't have permissions
|
return False # Doesn't have permissions
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def serializer_to_form_fields(self, serializer):
|
|
||||||
fields = {}
|
|
||||||
for k, v in serializer.get_fields().items():
|
|
||||||
if getattr(v, 'read_only', True):
|
|
||||||
continue
|
|
||||||
|
|
||||||
kwargs = {}
|
|
||||||
kwargs['required'] = v.required
|
|
||||||
|
|
||||||
#if getattr(v, 'queryset', None):
|
|
||||||
# kwargs['queryset'] = v.queryset
|
|
||||||
|
|
||||||
if getattr(v, 'choices', None) is not None:
|
|
||||||
kwargs['choices'] = v.choices
|
|
||||||
|
|
||||||
if getattr(v, 'regex', None) is not None:
|
|
||||||
kwargs['regex'] = v.regex
|
|
||||||
|
|
||||||
if getattr(v, 'widget', None):
|
|
||||||
widget = copy.deepcopy(v.widget)
|
|
||||||
kwargs['widget'] = widget
|
|
||||||
|
|
||||||
if getattr(v, 'default', None) is not None:
|
|
||||||
kwargs['initial'] = v.default
|
|
||||||
|
|
||||||
if getattr(v, 'label', None) is not None:
|
|
||||||
kwargs['label'] = v.label
|
|
||||||
|
|
||||||
if getattr(v, 'help_text', None) is not None:
|
|
||||||
kwargs['help_text'] = v.help_text
|
|
||||||
|
|
||||||
fields[k] = v.form_field_class(**kwargs)
|
|
||||||
|
|
||||||
return fields
|
|
||||||
|
|
||||||
def _get_form(self, view, method, request):
|
def _get_form(self, view, method, request):
|
||||||
# We need to impersonate a request with the correct method,
|
# We need to impersonate a request with the correct method,
|
||||||
# so that eg. any dynamic get_serializer_class methods return the
|
# so that eg. any dynamic get_serializer_class methods return the
|
||||||
|
@ -447,14 +465,7 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
return
|
return
|
||||||
|
|
||||||
serializer = view.get_serializer(instance=obj)
|
serializer = view.get_serializer(instance=obj)
|
||||||
fields = self.serializer_to_form_fields(serializer)
|
return HTMLFormRenderer().render(serializer, obj, 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)
|
|
||||||
return form_instance
|
|
||||||
|
|
||||||
def get_raw_data_form(self, view, method, request, media_types):
|
def get_raw_data_form(self, view, method, request, media_types):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -136,9 +136,9 @@
|
||||||
{% if post_form %}
|
{% if post_form %}
|
||||||
<div class="tab-pane" id="object-form">
|
<div class="tab-pane" id="object-form">
|
||||||
{% with form=post_form %}
|
{% with form=post_form %}
|
||||||
<form action="{{ request.get_full_path }}" method="POST" {% if form.is_multipart %}enctype="multipart/form-data"{% endif %} class="form-horizontal">
|
<form action="{{ request.get_full_path }}" method="POST" enctype="multipart/form-data" class="form-horizontal">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
{% include "rest_framework/form.html" %}
|
{{ post_form }}
|
||||||
<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>
|
||||||
|
@ -174,16 +174,14 @@
|
||||||
<div class="well tab-content">
|
<div class="well tab-content">
|
||||||
{% if put_form %}
|
{% if put_form %}
|
||||||
<div class="tab-pane" id="object-form">
|
<div class="tab-pane" id="object-form">
|
||||||
{% with form=put_form %}
|
<form action="{{ request.get_full_path }}" method="POST" enctype="multipart/form-data" class="form-horizontal">
|
||||||
<form action="{{ request.get_full_path }}" method="POST" {% if form.is_multipart %}enctype="multipart/form-data"{% endif %} class="form-horizontal">
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
{% include "rest_framework/form.html" %}
|
{{ put_form }}
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
{% endwith %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div {% if put_form %}class="tab-pane"{% endif %} id="generic-content-form">
|
<div {% if put_form %}class="tab-pane"{% endif %} id="generic-content-form">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user