stash
This commit is contained in:
parent
32addb8ed1
commit
2f8683add1
15 changed files with 610 additions and 134 deletions
|
|
@ -6,6 +6,46 @@ from files.serializers import FileSerializer
|
|||
from toolshed.models import Category, Property, ItemProperty, InventoryItem, Tag, StorageLocation, WorkflowInstance
|
||||
|
||||
|
||||
def parse_handle(handle):
|
||||
"""Parse a fully qualified handle like 'git:base#property:length' into (origin, entity_type, name)"""
|
||||
if '#' not in handle:
|
||||
# Fallback to old format (just name)
|
||||
return None, None, handle
|
||||
origin, rest = handle.split('#', 1)
|
||||
if ':' not in rest:
|
||||
return origin, None, rest
|
||||
entity_type, name = rest.split(':', 1)
|
||||
return origin, entity_type, name
|
||||
|
||||
|
||||
def resolve_category_handle(handle):
|
||||
"""Resolve a fully qualified handle to a Category object"""
|
||||
origin, entity_type, name = parse_handle(handle)
|
||||
if origin and entity_type == 'category':
|
||||
return Category.objects.get(origin=origin, name=name)
|
||||
# Fallback to name-only lookup
|
||||
return Category.objects.get(name=handle.split('/')[-1])
|
||||
|
||||
|
||||
def resolve_property_handle(handle):
|
||||
"""Resolve a fully qualified handle to a Property object"""
|
||||
origin, entity_type, name = parse_handle(handle)
|
||||
if origin and entity_type == 'property':
|
||||
return Property.objects.get(origin=origin, name=name)
|
||||
# Fallback to name-only lookup
|
||||
return Property.objects.get(name=handle)
|
||||
|
||||
|
||||
def resolve_tag_handle(handle):
|
||||
"""Resolve a fully qualified handle to a Tag object"""
|
||||
origin, entity_type, name = parse_handle(handle)
|
||||
if origin and entity_type == 'tag':
|
||||
return Tag.objects.get(origin=origin, name=name)
|
||||
# Fallback to name-only lookup
|
||||
return Tag.objects.get(name=handle)
|
||||
|
||||
|
||||
|
||||
class FriendSerializer(serializers.ModelSerializer):
|
||||
username = serializers.SerializerMethodField()
|
||||
|
||||
|
|
@ -29,23 +69,35 @@ class FriendRequestSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class PropertySerializer(serializers.ModelSerializer):
|
||||
category = serializers.SlugRelatedField(queryset=Category.objects.all(), slug_field='name')
|
||||
category = serializers.SerializerMethodField()
|
||||
handle = serializers.SerializerMethodField()
|
||||
|
||||
def get_category(self, obj):
|
||||
return resolve_category_handle(obj.category.get_handle()) if obj.category else None
|
||||
|
||||
def get_handle(self, obj):
|
||||
return obj.get_handle()
|
||||
|
||||
class Meta:
|
||||
model = Property
|
||||
fields = ['name', 'description', 'category', 'unit_symbol', 'unit_name', 'unit_name_plural', 'base2_prefix']
|
||||
fields = ['name', 'description', 'category', 'unit_symbol', 'unit_name', 'unit_name_plural', 'base2_prefix', 'handle']
|
||||
|
||||
|
||||
class CategorySerializer(serializers.ModelSerializer):
|
||||
handle = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = ['name']
|
||||
fields = ['name', 'handle']
|
||||
|
||||
def get_handle(self, obj):
|
||||
return obj.get_handle()
|
||||
|
||||
def to_representation(self, instance):
|
||||
return str(instance)
|
||||
return instance.get_handle()
|
||||
|
||||
def to_internal_value(self, data):
|
||||
return Category.objects.get(name=data.split("/")[-1])
|
||||
return resolve_category_handle(data.split("/")[-1])
|
||||
|
||||
|
||||
class StorageLocationSerializer(serializers.ModelSerializer):
|
||||
|
|
@ -67,23 +119,28 @@ class StorageLocationSerializer(serializers.ModelSerializer):
|
|||
|
||||
class ItemPropertySerializer(serializers.ModelSerializer):
|
||||
property = PropertySerializer(read_only=True)
|
||||
handle = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = ItemProperty
|
||||
fields = ['property', 'value']
|
||||
fields = ['property', 'value', 'handle']
|
||||
|
||||
def get_handle(self, obj):
|
||||
return obj.property.get_handle()
|
||||
|
||||
def to_representation(self, instance):
|
||||
return {'value': instance.value, 'name': instance.property.name}
|
||||
return {'value': instance.value, 'name': instance.property.name, 'handle': instance.property.get_handle()}
|
||||
|
||||
def to_internal_value(self, data):
|
||||
prop = Property.objects.get(name=data['name'])
|
||||
prop = resolve_property_handle(data.get('name') or data.get('handle'))
|
||||
value = data['value']
|
||||
return {'property': prop, 'value': value}
|
||||
|
||||
|
||||
class InventoryItemSerializer(serializers.ModelSerializer):
|
||||
owner = OwnerSerializer(read_only=True)
|
||||
tags = serializers.SlugRelatedField(many=True, required=False, queryset=Tag.objects.all(), slug_field='name')
|
||||
tags = serializers.SerializerMethodField()
|
||||
tags_input = serializers.ListField(child=serializers.CharField(), write_only=True, required=False)
|
||||
properties = ItemPropertySerializer(many=True, required=False, source='itemproperty_set')
|
||||
category = CategorySerializer(required=False, allow_null=True)
|
||||
files = FileSerializer(many=True, read_only=True)
|
||||
|
|
@ -91,11 +148,16 @@ class InventoryItemSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = InventoryItem
|
||||
fields = ['id', 'name', 'description', 'owner', 'category', 'availability_policy', 'owned_quantity', 'owner',
|
||||
'tags', 'properties', 'files', 'storage_location']
|
||||
'tags', 'tags_input', 'properties', 'files', 'storage_location']
|
||||
|
||||
def get_tags(self, obj):
|
||||
return [tag.get_handle() for tag in obj.tags.all()]
|
||||
|
||||
def to_internal_value(self, data):
|
||||
files = data.pop('files', [])
|
||||
tags_input = data.pop('tags_input', data.pop('tags', []))
|
||||
ret = super().to_internal_value(data)
|
||||
ret['tags'] = [resolve_tag_handle(tag) for tag in tags_input]
|
||||
ret['files'] = files
|
||||
return ret
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue