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
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)