mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-26 19:43:59 +03:00
Merge branch 'master' into 3.0-beta
This commit is contained in:
commit
d80d58e91a
|
@ -13,6 +13,23 @@ from rest_framework.compat import force_text
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
def _force_text_recursive(data):
|
||||||
|
"""
|
||||||
|
Descend into a nested data structure, forcing any
|
||||||
|
lazy translation strings into plain text.
|
||||||
|
"""
|
||||||
|
if isinstance(data, list):
|
||||||
|
return [
|
||||||
|
_force_text_recursive(item) for item in data
|
||||||
|
]
|
||||||
|
elif isinstance(data, dict):
|
||||||
|
return dict([
|
||||||
|
(key, _force_text_recursive(value))
|
||||||
|
for key, value in data.items()
|
||||||
|
])
|
||||||
|
return force_text(data)
|
||||||
|
|
||||||
|
|
||||||
class APIException(Exception):
|
class APIException(Exception):
|
||||||
"""
|
"""
|
||||||
Base class for REST framework exceptions.
|
Base class for REST framework exceptions.
|
||||||
|
@ -38,19 +55,6 @@ class APIException(Exception):
|
||||||
# from rest_framework import serializers
|
# from rest_framework import serializers
|
||||||
# raise serializers.ValidationError('Value was invalid')
|
# raise serializers.ValidationError('Value was invalid')
|
||||||
|
|
||||||
def force_text_recursive(data):
|
|
||||||
if isinstance(data, list):
|
|
||||||
return [
|
|
||||||
force_text_recursive(item) for item in data
|
|
||||||
]
|
|
||||||
elif isinstance(data, dict):
|
|
||||||
return dict([
|
|
||||||
(key, force_text_recursive(value))
|
|
||||||
for key, value in data.items()
|
|
||||||
])
|
|
||||||
return force_text(data)
|
|
||||||
|
|
||||||
|
|
||||||
class ValidationError(APIException):
|
class ValidationError(APIException):
|
||||||
status_code = status.HTTP_400_BAD_REQUEST
|
status_code = status.HTTP_400_BAD_REQUEST
|
||||||
|
|
||||||
|
@ -59,7 +63,7 @@ class ValidationError(APIException):
|
||||||
# The details should always be coerced to a list if not already.
|
# The details should always be coerced to a list if not already.
|
||||||
if not isinstance(detail, dict) and not isinstance(detail, list):
|
if not isinstance(detail, dict) and not isinstance(detail, list):
|
||||||
detail = [detail]
|
detail = [detail]
|
||||||
self.detail = force_text_recursive(detail)
|
self.detail = _force_text_recursive(detail)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.detail)
|
return str(self.detail)
|
||||||
|
|
|
@ -181,6 +181,9 @@ class Field(object):
|
||||||
self.style = {} if style is None else style
|
self.style = {} if style is None else style
|
||||||
self.allow_null = allow_null
|
self.allow_null = allow_null
|
||||||
|
|
||||||
|
if allow_null and self.default_empty_html is empty:
|
||||||
|
self.default_empty_html = None
|
||||||
|
|
||||||
if validators is not None:
|
if validators is not None:
|
||||||
self.validators = validators[:]
|
self.validators = validators[:]
|
||||||
|
|
||||||
|
@ -495,6 +498,7 @@ class CharField(Field):
|
||||||
}
|
}
|
||||||
initial = ''
|
initial = ''
|
||||||
coerce_blank_to_null = False
|
coerce_blank_to_null = False
|
||||||
|
default_empty_html = ''
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.allow_blank = kwargs.pop('allow_blank', False)
|
self.allow_blank = kwargs.pop('allow_blank', False)
|
||||||
|
|
|
@ -429,7 +429,10 @@ class HTMLFormRenderer(BaseRenderer):
|
||||||
style['base_template'] = self.base_template
|
style['base_template'] = self.base_template
|
||||||
style['renderer'] = self
|
style['renderer'] = self
|
||||||
|
|
||||||
if 'template' in style:
|
# This API needs to be finessed and finalized for 3.1
|
||||||
|
if 'template' in renderer_context:
|
||||||
|
template_name = renderer_context['template']
|
||||||
|
elif 'template' in style:
|
||||||
template_name = style['template']
|
template_name = style['template']
|
||||||
else:
|
else:
|
||||||
template_name = style['template_pack'].strip('/') + '/' + style['base_template']
|
template_name = style['template_pack'].strip('/') + '/' + style['base_template']
|
||||||
|
@ -555,7 +558,14 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
if data is not None:
|
if data is not None:
|
||||||
serializer.is_valid()
|
serializer.is_valid()
|
||||||
form_renderer = self.form_renderer_class()
|
form_renderer = self.form_renderer_class()
|
||||||
return form_renderer.render(serializer.data, self.accepted_media_type, self.renderer_context)
|
return form_renderer.render(
|
||||||
|
serializer.data,
|
||||||
|
self.accepted_media_type,
|
||||||
|
dict(
|
||||||
|
self.renderer_context.items() +
|
||||||
|
[('template', 'rest_framework/api_form.html')]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def get_raw_data_form(self, data, view, method, request):
|
def get_raw_data_form(self, data, view, method, request):
|
||||||
"""
|
"""
|
||||||
|
|
8
rest_framework/templates/rest_framework/api_form.html
Normal file
8
rest_framework/templates/rest_framework/api_form.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{% load rest_framework %}
|
||||||
|
{% csrf_token %}
|
||||||
|
{% for field in form %}
|
||||||
|
{% if not field.read_only %}
|
||||||
|
{% render_field field style=style %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<!-- form.non_field_errors -->
|
|
@ -4,6 +4,9 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<select class="form-control" name="{{ field.name }}">
|
<select class="form-control" name="{{ field.name }}">
|
||||||
|
{% if field.allow_null %}
|
||||||
|
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
|
||||||
|
{% endif %}
|
||||||
{% for key, text in field.choices.items %}
|
{% for key, text in field.choices.items %}
|
||||||
<option value="{{ key }}" {% if key == field.value %}selected{% endif %}>{{ text }}</option>
|
<option value="{{ key }}" {% if key == field.value %}selected{% endif %}>{{ text }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
<label class="sr-only">{{ field.label }}</label>
|
<label class="sr-only">{{ field.label }}</label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<select class="form-control" name="{{ field.name }}">
|
<select class="form-control" name="{{ field.name }}">
|
||||||
|
{% if field.allow_null %}
|
||||||
|
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
|
||||||
|
{% endif %}
|
||||||
{% for key, text in field.choices.items %}
|
{% for key, text in field.choices.items %}
|
||||||
<option value="{{ key }}" {% if key == field.value %}selected{% endif %}>{{ text }}</option>
|
<option value="{{ key }}" {% if key == field.value %}selected{% endif %}>{{ text }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
<label {% if style.hide_label %}class="sr-only"{% endif %}>{{ field.label }}</label>
|
<label {% if style.hide_label %}class="sr-only"{% endif %}>{{ field.label }}</label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<select class="form-control" name="{{ field.name }}">
|
<select class="form-control" name="{{ field.name }}">
|
||||||
|
{% if field.allow_null %}
|
||||||
|
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
|
||||||
|
{% endif %}
|
||||||
{% for key, text in field.choices.items %}
|
{% for key, text in field.choices.items %}
|
||||||
<option value="{{ key }}" {% if key == field.value %}selected{% endif %}>{{ text }}</option>
|
<option value="{{ key }}" {% if key == field.value %}selected{% endif %}>{{ text }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user