示例#1
0
    def build_composite_field(
            self, field_name: str, type_info: TypeInfo,
            extra_kwargs: KWArgs) -> SerializerFieldDefinition:
        """
        Create a composite (mapping or list) field.
        """
        # Lookup the types from the field mapping, so that it can easily be changed without overriding the method.
        if type_info.is_mapping:
            field_class = self.serializer_field_mapping[dict]
        else:
            field_class = self.serializer_field_mapping[list]

        # If the base type is not specified or is any type, we don't have to bother creating the child field.
        if type_info.base_type is None:
            return field_class, {}

        # Recurse to build the child field (i.e. the field of every instance). We pass the extra kwargs that are
        # specified for the child field through, so these can be used to recursively specify kwargs for child fields.
        extra_child_field_kwargs = extra_kwargs.get('child_kwargs', {})
        base_type_info = field_utils.get_type_info(type_info.base_type)
        child_field_class, child_field_kwargs = self.build_typed_field(
            field_name, base_type_info, extra_child_field_kwargs)

        # Include the extra kwargs specified for the child field before instantiating it.
        child_field_kwargs = self.include_extra_kwargs(
            child_field_kwargs, extra_child_field_kwargs)

        # Create child field and initialize parent field kwargs
        child_field = child_field_class(**child_field_kwargs)
        field_kwargs = {'child': child_field}
        return field_class, field_kwargs
    def build_composite_field(
            self, definition: DataclassDefinition, field_name: str,
            type_info: TypeInfo,
            extra_kwargs: KWArgs) -> SerializerFieldDefinition:
        """
        Create a composite (mapping or list) field.
        """
        # Recurse to build the child field (i.e. the field of every instance). We pass the extra kwargs that are
        # specified for the child field through, so these can be used to recursively specify kwargs for child fields.
        extra_child_field_kwargs = extra_kwargs.get('child_kwargs', {})
        base_type_info = field_utils.get_type_info(type_info.base_type)
        child_field_class, child_field_kwargs = self.build_typed_field(
            definition, field_name, base_type_info, extra_child_field_kwargs)

        # Include the extra kwargs specified for the child field before instantiating it.
        child_field_kwargs = self.include_extra_kwargs(
            child_field_kwargs, extra_child_field_kwargs)

        # Create child field and initialize parent field kwargs
        child_field = child_field_class(**child_field_kwargs)
        field_kwargs = {
            'allow_null': type_info.is_optional,
            'child': child_field
        }

        if type_info.is_mapping:
            field_class = rest_framework.fields.DictField
        else:
            field_class = rest_framework.fields.ListField

        return field_class, field_kwargs
示例#3
0
    def create_field(self, field_name: str,
                     extra_kwargs: KWArgs) -> SerializerField:
        # Get the source field (this can be useful to represent a single dataclass field in multiple ways in the
        # serialization state).
        source = extra_kwargs.get('source', '*')
        if source == '*':
            source = field_name

        # Determine the serializer field class and keyword arguments.
        if source in self.dataclass_definition.fields:
            default_value = self.dataclass_definition.fields[source].default
            default_type = type(
                default_value) if default_value is not None else None
            type_info = field_utils.get_type_info(
                self.dataclass_definition.field_types[source], default_type)
            field_class, field_kwargs = self.build_typed_field(
                source, type_info, extra_kwargs)
        elif hasattr(self.dataclass_definition.dataclass_type, source):
            field_class, field_kwargs = self.build_property_field(source)
        else:
            field_class, field_kwargs = self.build_unknown_field(source)

        # Include any extra kwargs defined through `Meta.extra_kwargs`
        field_kwargs = self.include_extra_kwargs(field_kwargs, extra_kwargs)

        # Create the serializer field instance.
        return field_class(**field_kwargs)
    def build_typed_field(self, type_hint, extra_kwargs=None):
        testclass = dataclasses.make_dataclass('TestDataclass', [('test_field', type_hint)])
        serializer = DataclassSerializer(dataclass=testclass)
        type_info = field_utils.get_type_info(serializer.dataclass_definition.field_types['test_field'])

        extra_kwargs = extra_kwargs or {}
        return serializer.build_typed_field('test_field', type_info, extra_kwargs)