mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-29 17:39:48 +03:00
raise error when calling .data
in an invalid serializer
This commit is contained in:
parent
b25d245b89
commit
9280d7f811
|
@ -34,6 +34,7 @@ from rest_framework.settings import api_settings
|
|||
from rest_framework.utils import encoders, json
|
||||
from rest_framework.utils.breadcrumbs import get_breadcrumbs
|
||||
from rest_framework.utils.field_mapping import ClassLookupDict
|
||||
from rest_framework.utils.serializer_helpers import ReturnDict
|
||||
|
||||
|
||||
def zero_as_none(value):
|
||||
|
@ -522,12 +523,14 @@ class BrowsableAPIRenderer(BaseRenderer):
|
|||
return self.render_form_for_serializer(serializer)
|
||||
|
||||
def render_form_for_serializer(self, serializer):
|
||||
if hasattr(serializer, 'initial_data'):
|
||||
serializer.is_valid()
|
||||
if hasattr(serializer, 'initial_data') and not serializer.is_valid():
|
||||
data = ReturnDict(serializer.get_initial(), serializer=serializer)
|
||||
else:
|
||||
data = serializer.data
|
||||
|
||||
form_renderer = self.form_renderer_class()
|
||||
return form_renderer.render(
|
||||
serializer.data,
|
||||
data,
|
||||
self.accepted_media_type,
|
||||
{'style': {'template_pack': 'rest_framework/horizontal'}}
|
||||
)
|
||||
|
|
|
@ -262,6 +262,9 @@ class BaseSerializer(Field):
|
|||
self._data = self.to_representation(self.instance)
|
||||
elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
|
||||
self._data = self.to_representation(self.validated_data)
|
||||
elif hasattr(self, '_validated_data') and getattr(self, '_errors', None):
|
||||
msg = 'You can not access `.data` in an invalid serializer.'
|
||||
raise AssertionError(msg)
|
||||
else:
|
||||
self._data = self.get_initial()
|
||||
return self._data
|
||||
|
@ -547,7 +550,13 @@ class Serializer(BaseSerializer):
|
|||
|
||||
def __getitem__(self, key):
|
||||
field = self.fields[key]
|
||||
value = self.data.get(key)
|
||||
|
||||
# If the data is not valid, return the initial data
|
||||
if not hasattr(self, '_data') and hasattr(self, '_validated_data') and getattr(self, '_errors', None):
|
||||
value = self.get_initial().get(key)
|
||||
else:
|
||||
value = self.data.get(key)
|
||||
|
||||
error = self.errors.get(key) if hasattr(self, '_errors') else None
|
||||
if isinstance(field, Serializer):
|
||||
return NestedBoundField(field, value, error)
|
||||
|
|
|
@ -13,6 +13,7 @@ from django.utils.safestring import SafeData, mark_safe
|
|||
|
||||
from rest_framework.compat import apply_markdown, pygments_highlight
|
||||
from rest_framework.renderers import HTMLFormRenderer
|
||||
from rest_framework.utils.serializer_helpers import ReturnDict
|
||||
from rest_framework.utils.urls import replace_query_param
|
||||
|
||||
register = template.Library()
|
||||
|
@ -79,9 +80,14 @@ def get_pagination_html(pager):
|
|||
|
||||
@register.simple_tag
|
||||
def render_form(serializer, template_pack=None):
|
||||
if hasattr(serializer, 'initial_data') and not serializer.is_valid():
|
||||
data = ReturnDict(serializer.get_initial(), serializer=serializer)
|
||||
else:
|
||||
data = serializer.data
|
||||
|
||||
style = {'template_pack': template_pack} if template_pack else {}
|
||||
renderer = HTMLFormRenderer()
|
||||
return renderer.render(serializer.data, None, {'style': style})
|
||||
return renderer.render(data, None, {'style': style})
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
|
|
|
@ -499,7 +499,7 @@ class TestHTMLFormRenderer(TestCase):
|
|||
test_field = serializers.CharField()
|
||||
|
||||
self.renderer = HTMLFormRenderer()
|
||||
self.serializer = TestSerializer(data={})
|
||||
self.serializer = TestSerializer(data={'test_field': 'test'})
|
||||
|
||||
def test_render_with_default_args(self):
|
||||
self.serializer.is_valid()
|
||||
|
|
|
@ -86,15 +86,17 @@ class TestSerializer:
|
|||
serializer = self.Serializer(data={'char': 'abc'})
|
||||
assert not serializer.is_valid()
|
||||
assert serializer.validated_data == {}
|
||||
assert serializer.data == {'char': 'abc'}
|
||||
assert serializer.errors == {'integer': ['This field is required.']}
|
||||
with pytest.raises(AssertionError):
|
||||
serializer.data
|
||||
|
||||
def test_invalid_datatype(self):
|
||||
serializer = self.Serializer(data=[{'char': 'abc'}])
|
||||
assert not serializer.is_valid()
|
||||
assert serializer.validated_data == {}
|
||||
assert serializer.data == {}
|
||||
assert serializer.errors == {'non_field_errors': ['Invalid data. Expected a dictionary, but got list.']}
|
||||
with pytest.raises(AssertionError):
|
||||
serializer.data
|
||||
|
||||
def test_partial_validation(self):
|
||||
serializer = self.Serializer(data={'char': 'abc'}, partial=True)
|
||||
|
@ -208,11 +210,12 @@ class TestSerializer:
|
|||
|
||||
serializer = ExampleSerializer(data=data)
|
||||
assert not serializer.is_valid()
|
||||
assert serializer.data == data
|
||||
assert serializer.validated_data == {}
|
||||
assert serializer.errors == {'char': [
|
||||
exceptions.ErrorDetail(string='Raised error', code='invalid')
|
||||
]}
|
||||
with pytest.raises(AssertionError):
|
||||
serializer.data
|
||||
|
||||
|
||||
class TestValidateMethod:
|
||||
|
|
Loading…
Reference in New Issue
Block a user