rest_witchcraft.serializers module

class rest_witchcraft.serializers.BaseSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: rest_framework.serializers.Serializer

build_standard_field(field_name, column_info)[source]

Create regular model fields.

build_standard_field_kwargs(field_name, field_class, column_info)[source]

Analyze model column to generate field kwargs.

create(validated_data)[source]
get_field_type(column_info)[source]

Returns the field type to be used determined by the sqlalchemy column type or the column type’s python type.

include_extra_kwargs(kwargs, extra_kwargs=None)[source]

Include any ‘extra_kwargs’ that have been included for this field, possibly removing any incompatible existing keyword arguments.

is_nested
serializer_choice_field

alias of rest_framework.fields.ChoiceField

update(instance, validated_data)[source]
update_attribute(instance, field, value)[source]

Performs update on the instance for the given field with value.

class rest_witchcraft.serializers.CompositeSerializer(*args, **kwargs)[source]

Bases: rest_witchcraft.serializers.BaseSerializer

This class is useful for generating a serializer for sqlalchemy’s composite model attributes.

create(validated_data)[source]
get_fields()[source]

Return the dict of field names -> field instances that should be used for self.fields when instantiating the serializer.

get_object(validated_data, instance=None)[source]
perform_update(instance, validated_data, errors)[source]
update(instance, validated_data)[source]
class rest_witchcraft.serializers.ExpandableModelSerializer(*args, **kwargs)[source]

Bases: rest_witchcraft.serializers.ModelSerializer

Same as ModelSerializer but allows to conditionally recursively expand specific fields.

Serializer by default renders with all fields collapsed however validates data with expanded fields.

To expand fields, either:

  • request.GET should request to expand field by ?expand=<field>. Field names can be recursive ?expand=<field>__<nested_field>.
  • One of expandable fields was updated which will cause to_representation() to render expanded field.

By default serializer should define “expanded” fields. ModelSerializer already does it by default for all relations. This allows introspection of not rendered serializer to pick up all fields. This is especially useful when generating schema for the serializer such as for coreapi docs. Collapsed fields are specified in Meta.expandable_fields where keys are field names and values are replacement field instances.

In addition expandable query key can be specified via Meta.expandable_query_key.

For example:

class BarJustIDSerializer(Serializer):
    id = serializers.IntegerField(source="bar_id")

    class Meta:
        model = Bar
        session = session
        fields = ["id"]

class FooSerializer(ExpandableModelSerializer):
    class Meta:
        model = Foo
        session = session
        exclude = ["bar_id"]
        expandable_fields = {
            "bar": BarJustIDSerializer(source="*", read_only=True)
        }
        expandable_query_key = "include"

Additionally, query serializer can be autogenerated to be used to either validate request query or generate documentation:

FooSerializer().get_query_serializer_class()
FooSerializer().get_query_serializer_class(exclude=["bar"])
FooSerializer().get_query_serializer_class(disallow=["bar"])
Exclude:excludes given expand paths. Useful for generating documentation.
Disallow:leaves the expand field in serializer however removes given paths from valid choices. Useful for validating user input within viewset.
get_query_serializer_class(exclude=(), disallow=(), implicit_expand=True)[source]

Generate serializer to either validate request querystring or generate documentation.

to_representation(instance)[source]

Switch expandable fields to collapsed fields if not explicitly asked to be expanded or field was updated.

update_attribute(instance, field, value)[source]

Mark which attributes are updated so that during representation of the resource, we can expand those fields even if not explicitly asked for.

Fields are marked on root serializer since child serializers should not contain any state.

class rest_witchcraft.serializers.ModelSerializer(*args, **kwargs)[source]

Bases: rest_witchcraft.serializers.BaseSerializer

ModelSerializer is basically like a drf model serializer except that it works with sqlalchemy models:

  • A set of default fields are automatically populated by introspecting a sqlalchemy model
  • Default .create() and .update() implementations provided by mostly reducing the problem to update.

The process of automatically determining a set of serializer fields is based on the model’s fields, components and relationships.

If the ModelSerializer does not generate the set of fields that you need, you can explicitly declare them.

build_composite_field(field_name, composite)[source]

Builds a CompositeSerializer to handle composite attribute in model.

build_field(field_name, info, model_class, nested_depth)[source]

Return a field or a nested serializer for the field name.

build_nested_field(field_name, relation_info, nested_depth)[source]

Builds nested serializer to handle relationshipped model.

build_primary_key_field(field_name, column_info)[source]

Builds a field for the primary key of the model.

build_property_field(field_name, info)[source]
build_unknown_field(field_name, info)[source]

Raise an error on any unknown fields.

build_url_field(field_name, info)[source]

Create a field representing the object’s own URL.

create(validated_data)[source]

Creates a model instance using validated_data.

create_model(validated_data)[source]

Hook to allow to customize how model is created in create flow.

default_error_messages = {'not_found': 'No instance found with primary keys'}
get_default_field_names(declared_fields, info)[source]

Return the default list of field names that will be used if the Meta.fields option is not specified.

get_extra_kwargs(**additional_kwargs)[source]

Return a dictionary mapping field names to a dictionary of additional keyword arguments.

get_field_names(declared_fields, info)[source]

Returns the list of all field names that should be created when instantiating this serializer class.

This is based on the default set of fields, but also takes into account the Meta.fields or Meta.exclude options if they have been specified.

get_fields()[source]

Return the dict of field names -> field instances that should be used for self.fields when instantiating the serializer.

get_nested_relationship_fields(relation_info, depth)[source]

Get the field names for the nested serializer.

get_object(validated_data, instance=None)[source]

Returns model object instance using the primary key values in the validated_data.

If the instance is not found, depending on serializer’s allow_create value, it will create a new model instance or raise an error.

get_primary_keys(validated_data)[source]

Returns the primary key values from validated_data.

get_relationship_kwargs(relation_info, depth)[source]

Figure out the arguments to be used in the NestedSerializer for the relationship.

model
perform_flush()[source]

Perform session flush changes.

perform_update(instance, validated_data, errors)[source]

The main nested update logic implementation using nested fields and serializer.

query_model(pks)[source]

Hook to allow to customize how model is queried when serializer is nested and needs to query the model by its primary keys.

queryset
save(**kwargs)[source]

Save and return a list of object instances.

serializer_url_field

alias of rest_witchcraft.fields.UriField

session
to_internal_value(data)[source]

Same as in DRF but also handle partial_by_pk by making all non- pk fields optional.

Even though flag name implies it will make serializer partial, that is currently not possible in DRF as partial flag is checked on root serializer within serializer validation loops. As such, individual serializers cannot be marked partial. Therefore when flag is provided and primary key is provided in validated data, we physically mark all other fields as not required to effectively make them partial without using partial flag itself. To make serializer behave more or less like real partial serializer, only passed keys in input data are preserved in validated data. If they are not stripped, it is possible to remove some existing data.

update(instance, validated_data)[source]

Updates an existing model instance using validated_data with suspended autoflush.

url_field_name = None