from rest_framework import serializers from taggit_serializer.serializers import TagListSerializerField, TaggitSerializer class SingleTag(str): def __init__(self, *args, **kwargs): pass def __str__(self): return self class SingleTagSerializerField(serializers.Field): child = serializers.CharField() default_error_messages = { 'not_a_str': 'Expected a string but got type "{input_type}".', } order_by = None def __init__(self, **kwargs): super(SingleTagSerializerField, self).__init__(**kwargs) def to_internal_value(self, value): if isinstance(value, str): if not value: value = "" if not isinstance(value, str): self.fail('not_a_str', input_type=type(value).__name__) return value def to_representation(self, value): if not isinstance(value, SingleTag): if not isinstance(value, str): value = value.name value = SingleTag(value) return value class CustomTagSerializer(serializers.Serializer): def create(self, validated_data): to_be_tagged, validated_data = self._pop_tags(validated_data) tag_object = super(CustomTagSerializer, self).create(validated_data) return self._save_tags(tag_object, to_be_tagged) def update(self, instance, validated_data): to_be_tagged, validated_data = self._pop_tags(validated_data) tag_object = super(CustomTagSerializer, self).update( instance, validated_data) return self._save_tags(tag_object, to_be_tagged) def _save_tags(self, tag_object, tags): for key in tags.keys(): tag_values = tags.get(key) getattr(tag_object, key).set(*tag_values) return tag_object def _pop_tags(self, validated_data): to_be_tagged = {} import ipdb; ipdb.set_trace() for key in self.fields.keys(): field = self.fields[key] if isinstance(field, TagListSerializerField): if key in validated_data: to_be_tagged[key] = validated_data.pop(key) return (to_be_tagged, validated_data)