from rest_framework import serializers from authentication.serializers import OwnerSerializer from hostadmin.models import Domain from toolshed.models import Category, Property, Tag class SlugPathField(serializers.SlugRelatedField): def to_internal_value(self, data): path = data.split('/') if '/' in data else [data] candidates = self.get_queryset().filter(name=path[-1]) if len(candidates) == 1: return candidates.first() if len(candidates) == 0: raise serializers.ValidationError( "No {} with name '{}' found".format(self.queryset.model.__name__, path[-1])) if len(candidates) > 1 and len(path) == 1: raise serializers.ValidationError("Multiple {}s with name '{}' found, please specify the parent".format( self.queryset.model.__name__, path[-1])) parent = self.to_internal_value('/'.join(path[:-1])) candidates = self.get_queryset().filter(name=path[-1], parent=parent) if len(candidates) == 1: return candidates.first() if len(candidates) == 0: raise serializers.ValidationError( "No {} with name '{}' found".format(self.queryset.model.__name__, path[-1])) def to_representation(self, value): source = getattr(value, self.field_name, None) # should this use self.source? prefix = self.to_representation(source) + '/' if source else '' return prefix + getattr(value, self.slug_field) class DomainSerializer(serializers.ModelSerializer): owner = OwnerSerializer(read_only=True) class Meta: model = Domain fields = ['name', 'owner', 'open_registration'] class CategorySerializer(serializers.ModelSerializer): parent = SlugPathField(slug_field='name', queryset=Category.objects.all(), required=False) def validate(self, attrs): if 'name' in attrs: if '/' in attrs['name']: raise serializers.ValidationError("Category name cannot contain '/'") return attrs def create(self, validated_data): try: return Category.objects.create(**validated_data) except Exception as e: raise serializers.ValidationError(e) class Meta: model = Category fields = ['name', 'description', 'parent', 'origin'] read_only_fields = ['origin'] ref_name = 'HostAdminCategory' class PropertySerializer(serializers.ModelSerializer): category = SlugPathField(slug_field='name', queryset=Category.objects.all(), required=False) def validate(self, attrs): if 'name' in attrs: if '/' in attrs['name']: raise serializers.ValidationError("Property name cannot contain '/'") return attrs def create(self, validated_data): try: return Property.objects.create(**validated_data) except Exception as e: raise serializers.ValidationError(e) class Meta: model = Property fields = ['name', 'description', 'category', 'unit_symbol', 'unit_name', 'unit_name_plural', 'base2_prefix', 'dimensions', 'origin'] read_only_fields = ['origin'] ref_name = 'HostAdminProperty' class TagSerializer(serializers.ModelSerializer): category = SlugPathField(slug_field='name', queryset=Category.objects.all(), required=False) def validate(self, attrs): if 'name' in attrs: if '/' in attrs['name']: raise serializers.ValidationError("Tag name cannot contain '/'") return attrs def create(self, validated_data): try: return Tag.objects.create(**validated_data) except Exception as e: raise serializers.ValidationError(e) class Meta: model = Tag fields = ['name', 'description', 'category', 'origin'] read_only_fields = ['origin'] ref_name = 'HostAdminTag'