def to_internal_value(self, data):
        """
        List of dicts of native values <- List of dicts of primitive datatypes.
        """
        if html.is_html_input(data):
            data = html.parse_html_list(data)

        if not isinstance(data, list):
            message = self.error_messages['not_a_list'].format(
                input_type=type(data).__name__
            )
            raise ValidationError({
                api_settings.NON_FIELD_ERRORS_KEY: [message]
            })

        ret = []
        errors = ReturnList(serializer=self)

        for item in data:
            try:
                validated = self.child.run_validation(item)
            except ValidationError as exc:
                errors.append(exc.detail)
            else:
                ret.append(validated)
                errors.append({})

        if any(errors):
            raise ValidationError(errors)

        return ret
示例#2
0
    def to_representation(self, instance):
        """Add addditonal data for the ViewFeatureSerializer.

        For most features, all the related data is cachable, and no database
        reads are required with a warm cache.

        For some features, such as the root node for CSS, the subtree is huge,
        and the descendant feature PKs won't fit in the cache.  In these
        cases, a couple of database reads are required to get the
        descendant feature PKs, which are then paginated to reduce the huge
        amount of related data.
        """
        # Load the paginated descendant features
        if instance is None:
            # This happens when OPTIONS is called from browsable API
            return None
        self.add_sources(instance)

        ret = OrderedDict()
        fields = self._readable_fields

        for field in fields:
            attribute = field.get_attribute(instance)
            assert attribute is not None, (
                'field.get_attribute return None for instance %s, field %s' %
                (instance, field))
            field_ret = field.to_representation(attribute)
            if isinstance(field, ListSerializer):
                # Wrap lists of related resources in a ReturnList, so that the
                # renderer has access to the serializer
                field_ret = ReturnList(field_ret, serializer=field)
            ret[field.field_name] = field_ret

        return ReturnDict(ret, serializer=self)
示例#3
0
    def test_compatibility_return_collections(self):
        """
        When the input with ReturnDict and ReturnList collections is processed by camelize() and then by underscorize(),
        the result should be same. Serializers should be preserved in all nested ReturnDict and ReturnList collections.
        """
        fake_serializer_instance_1 = (42, )
        fake_serializer_instance_2 = (42, )
        fake_serializer_instance_3 = (42, )
        input = ReturnDict(
            [("title_display", 1),
             ("a_list",
              ReturnList([
                  1, "two_three",
                  ReturnDict([("threee_four", 5)],
                             serializer=fake_serializer_instance_3)
              ],
                         serializer=fake_serializer_instance_2)),
             ("a_tuple", ("one_two", 3))],
            serializer=fake_serializer_instance_1)

        result = underscorize(camelize(input))
        self.assertEqual(result, input)
        self.assertIs(result.serializer, input.serializer)
        self.assertIs(result['a_list'].serializer, input['a_list'].serializer)
        self.assertIs(result['a_list'][2].serializer,
                      input['a_list'][2].serializer)
示例#4
0
    def data(self):
        if hasattr(self,
                   'initial_data') and not hasattr(self, '_validated_data'):
            msg = ('When a serializer is passed a `data` keyword argument you '
                   'must call `.is_valid()` before attempting to access the '
                   'serialized `.data` representation.\n'
                   'You should either call `.is_valid()` first, '
                   'or access `.initial_data` instead.')
            raise AssertionError(msg)

        if not hasattr(self, '_data'):
            if self.instance is not None and not getattr(
                    self, '_errors', None):
                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)
            else:
                self._data = self.get_initial()

        if isinstance(self._data, list):
            self._data = ReturnList(self._data, serializer=self)
        else:
            pass
        return self._data
示例#5
0
def _get_error_details(data, default_code=None):
    """加载错误详情

    :param data: 错误对象
    :param default_code: 默认错误码
    :return: 错误对象
    """
    if isinstance(data, list):
        ret = [_get_error_details(item, default_code) for item in data]
        if isinstance(data, ReturnList):
            return ReturnList(ret, serializer=data.serializer)
        return ret
    elif isinstance(data, dict):
        ret = {
            key: _get_error_details(value, default_code)
            for key, value in data.items()
        }
        if isinstance(data, ReturnDict):
            return ReturnDict(ret, serializer=data.serializer)
        return ret
    elif isinstance(data, Trans):
        return data

    text = force_text(data)
    code = getattr(data, 'code', default_code)
    return exceptions.ErrorDetail(text, code)
示例#6
0
 def data(self):
     # call grandparent's property
     ret = super(serializers.Serializer, self).data
     if isinstance(ret, dict):
         return ReturnDict(ret, serializer=self)
     if isinstance(ret, list):
         return ReturnList(ret, serializer=self)
     return ret
示例#7
0
 def data(self):
     """Get the data, after performing post-processing if necessary."""
     data = super(DynamicListSerializer, self).data
     processed_data = ReturnDict(
         SideloadingProcessor(self, data).data,
         serializer=self) if self.child.envelope else ReturnList(
             data, serializer=self)
     return processed_data
示例#8
0
 def data(self):
     """Get the data, after performing post-processing if necessary."""
     if not hasattr(self, '_sideloaded_data'):
         data = super(DynamicListSerializer, self).data
         if self.child.sideload:
             self._sideloaded_data = ReturnDict(SideloadingProcessor(
                 self, data).data,
                                                serializer=self)
         else:
             self._sideloaded_data = ReturnList(data, serializer=self)
     return self._sideloaded_data
示例#9
0
 def data(self):
     ret = super(serializers.ListSerializer, self).data
     if isinstance(ret, dict):
         # Override to make sure dict is preserved
         return ReturnDict(ret, serializer=self)
     elif inspect.isgenerator(ret):
         # Override to make sure the generator is preserved
         return ReturnGenerator(ret, serializer=self)
     else:
         # Normal behavior
         return ReturnList(ret, serializer=self)
示例#10
0
    def test_return_list(self):
        """
        camelize() should convert keys in all objects contained in an instance
        of rest_framework.utils.serializer_helpers.ReturnList and keep the same serializer.
        """
        fake_serializer_instance = (42, )

        input = ReturnList([{
            "title_display": 1
        }, {
            "title_field": 2
        }],
                           serializer=fake_serializer_instance)
        output = ReturnList([{
            "titleDisplay": 1
        }, {
            "titleField": 2
        }],
                            serializer=fake_serializer_instance)

        result = camelize(input)
        self.assertEqual(result, output)
        self.assertIs(result.serializer, output.serializer)
示例#11
0
    def test_renderer_works_correctly_with_return_list(self):
        """
        Ensure that rest_framework.utils.serializer_helpers.ReturnList
        is serialized correctly.
        """
        test_list = [{"1": 1}]
        rendered = self.renderer.render(
            data=ReturnList(test_list, serializer=None),
            media_type="application/json",
            renderer_context={},
        )
        reloaded = orjson.loads(rendered)

        self.assertEqual(reloaded, test_list)
示例#12
0
def _force_text_recursive(data):
    """
    Descend into a nested data structure, forcing any
    lazy translation strings into plain text.
    """
    if isinstance(data, list):
        ret = [_force_text_recursive(item) for item in data]
        if isinstance(data, ReturnList):
            return ReturnList(ret, serializer=data.serializer)
        return data
    elif isinstance(data, dict):
        ret = dict([(key, _force_text_recursive(value))
                    for key, value in data.items()])
        if isinstance(data, ReturnDict):
            return ReturnDict(ret, serializer=data.serializer)
        return data
    return force_text(data)
示例#13
0
def get_error_details(data, default_code=None):

    if isinstance(data, list):
        ret = [get_error_details(item, default_code) for item in data]
        if isinstance(data, ReturnList):
            return ReturnList(ret, serializer=data.serializer)
        return ret
    elif isinstance(data, dict):
        ret = {
            key: get_error_details(value, default_code)
            for key, value in data.items()
        }
        if isinstance(data, ReturnDict):
            return ReturnDict(ret, serializer=data.serializer)
        return ret

    text = force_str(data)
    code = getattr(data, 'code', default_code)
    return ErrorDetail(text, code)
示例#14
0
    def finalize_response(self, request, response, *args, **kwargs):
        """
        If the requested format is a spreadsheet, format the cell values before
        rendering the spreadsheet. Also perform the functionality of XLSXFileMixin.
        """
        response = super(XLSXFormatterMixin,
                         self).finalize_response(request, response, *args,
                                                 **kwargs)

        # If this is a spreadsheet response, intercept and format.
        if isinstance(
                response,
                Response) and response.accepted_renderer.format == "xlsx":
            self._field_dict = {}
            if isinstance(response.data, ReturnList):
                new_data = [
                    OrderedDict(
                        [self._format_cell(k, v) for k, v in row.items()])
                    for row in response.data
                ]
                response.data = ReturnList(new_data,
                                           serializer=response.data.serializer)
            elif isinstance(response.data, ReturnDict):
                new_data = OrderedDict([
                    self._format_cell(k, v) for k, v in response.data.items()
                ])
                response.data = ReturnDict(new_data,
                                           serializer=response.data.serializer)
            elif isinstance(response.data, dict):
                # If this is not a proper spreadsheet response (ex: object does not exist),
                # then return the response in JSON format.
                response = Response(response.data)
                response.accepted_renderer = JSONRenderer()
                response.accepted_media_type = "application/json"
                response.renderer_context = {}
                return response

            response["Content-Disposition"] = "attachment; filename={}".format(
                self.get_filename())

        return response
示例#15
0
    def wrap_paginated(self, data, renderer_context):
        """Convert paginated data to JSON API with meta"""

        pagination_keys = ['count', 'next', 'previous', 'results']
        for key in pagination_keys:
            if not (data and key in data):
                raise WrapperNotApplicable('Not paginated results')

        view = renderer_context.get("view", None)
        model = self.model_from_obj(view)
        resource_type = self.model_to_resource_type(model)

        try:
            from rest_framework.utils.serializer_helpers import ReturnList

            results = ReturnList(
                data["results"],
                serializer=data.serializer.fields["results"],
            )
        except ImportError:
            results = data["results"]

        # Use default wrapper for results
        wrapper = self.wrap_default(results, renderer_context)

        # Add pagination metadata
        pagination = self.dict_class()

        pagination['previous'] = data['previous']
        pagination['next'] = data['next']
        pagination['count'] = data['count']

        wrapper.setdefault('meta', self.dict_class())

        wrapper['meta'].setdefault('pagination', self.dict_class())
        wrapper['meta']['pagination'].setdefault(
            resource_type, self.dict_class()).update(pagination)

        return wrapper
示例#16
0
def _force_text_recursive(data):
    """
    Descend into a nested data structure, forcing any
    lazy translation strings into plain text.
    This modified version keeps tuples as is
    """
    if isinstance(data, (list, tuple)):
        ret = [_force_text_recursive(item) for item in data]
        if isinstance(data, ReturnList):
            return ReturnList(ret, serializer=data.serializer)
        if isinstance(data, tuple):
            return tuple(ret)
        return ret
    elif isinstance(data, dict):
        ret = {
            key: _force_text_recursive(value)
            for key, value in data.items()
        }
        if isinstance(data, ReturnDict):
            return ReturnDict(ret, serializer=data.serializer)
        return ret
    return force_text(data)
示例#17
0
def _get_error_details(data, default_code=None):
    """
    Descend into a nested data structure, forcing any
    lazy translation strings or strings into `ErrorDetail`.
    """
    if isinstance(data, list):
        ret = [_get_error_details(item, default_code) for item in data]
        if isinstance(data, ReturnList):
            return ReturnList(ret, serializer=data.serializer)
        return ret
    elif isinstance(data, dict):
        ret = {
            key: _get_error_details(value, default_code)
            for key, value in data.items()
        }
        if isinstance(data, ReturnDict):
            return ReturnDict(ret, serializer=data.serializer)
        return ret

    text = force_text(data)
    code = getattr(data, 'code', default_code)
    return ErrorDetail(text, code)
示例#18
0
 def make_list(self, data_list, serializer):
     list_serializer = ListSerializer(child=serializer)
     return ReturnList(data_list, serializer=list_serializer)
示例#19
0
 def errors(self):
     ret = super(ListSerializer, self).errors
     if isinstance(ret, dict):
         return ReturnDict(ret, serializer=self)
     return ReturnList(ret, serializer=self)
示例#20
0
 def test_encode_empty_returnlist(self):
     """
     Tests encoding an empty ReturnList
     """
     foo = ReturnList(serializer=None)
     assert self.encoder.default(foo) == []
示例#21
0
 def data_list(self):
     super().data
     return ReturnList(self._data, serializer=self)
示例#22
0
    def data(self):
        ret = super(serializers.Serializer, self).data

        return ReturnList(ret, serializer=self)
示例#23
0
 def data(self):
     returnlist = super().data
     fieldname = self.child.Meta.listresults_field
     return OrderedDict(
         {fieldname: ReturnList(returnlist, serializer=self)})