make dataset parsing more robust
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
j3d1 2024-03-11 17:37:56 +01:00
parent f2db5d9dad
commit 8cf0897ec5
13 changed files with 337 additions and 36 deletions

View file

@ -5,6 +5,32 @@ 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)
@ -12,12 +38,21 @@ class DomainSerializer(serializers.ModelSerializer):
model = Domain
fields = ['name', 'owner', 'open_registration']
def create(self, validated_data):
return super().create(validated_data)
class CategorySerializer(serializers.ModelSerializer):
parent = serializers.SlugRelatedField(slug_field='name', queryset=Category.objects.all(), required=False)
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
@ -27,7 +62,19 @@ class CategorySerializer(serializers.ModelSerializer):
class PropertySerializer(serializers.ModelSerializer):
category = serializers.SlugRelatedField(slug_field='name', queryset=Category.objects.all(), required=False)
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
@ -38,7 +85,19 @@ class PropertySerializer(serializers.ModelSerializer):
class TagSerializer(serializers.ModelSerializer):
category = serializers.SlugRelatedField(slug_field='name', queryset=Category.objects.all(), required=False)
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