| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- # ==================== Updated serializers.py ====================
- from rest_framework import serializers
- from .models import Product, ProductType, ProductAttribute, AttributePossibleValue
- class ProductInputSerializer(serializers.Serializer):
- """Serializer for individual product input."""
- product_id = serializers.CharField(required=False, allow_blank=True, allow_null=True)
- title = serializers.CharField(required=False, allow_blank=True, allow_null=True)
- short_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
- long_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
- image_url = serializers.URLField(required=False, allow_blank=True, allow_null=True)
- class MandatoryAttrsField(serializers.DictField):
- """Custom DictField to validate mandatory_attrs structure."""
- child = serializers.ListField(child=serializers.CharField())
- class ProductBatchInputSerializer(serializers.Serializer):
- """Serializer for an individual product input within the batch request."""
- item_id = serializers.CharField(required=True)
- mandatory_attrs = MandatoryAttrsField(
- required=True,
- help_text="A dictionary of attribute names and their possible values."
- )
- class SingleProductRequestSerializer(serializers.Serializer):
- """Serializer for single product extraction request."""
- item_id = serializers.CharField(required=True)
- mandatory_attrs = serializers.DictField(
- child=serializers.ListField(child=serializers.CharField()),
- required=True
- )
- model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
- extract_additional = serializers.BooleanField(required=False, default=True)
- process_image = serializers.BooleanField(required=False, default=True)
- multiple = serializers.ListField(
- child=serializers.CharField(),
- required=False,
- default=list,
- help_text="List of attribute names that can have multiple values"
- )
- threshold_abs = serializers.FloatField(default=0.65, required=False)
- margin = serializers.FloatField(default=0.15, required=False)
- use_dynamic_thresholds = serializers.BooleanField(default=True, required=False)
- use_adaptive_margin = serializers.BooleanField(default=True, required=False)
- use_semantic_clustering = serializers.BooleanField(default=True, required=False)
- def validate_model(self, value):
- from django.conf import settings
- if value not in settings.SUPPORTED_MODELS:
- raise serializers.ValidationError(
- f"Model must be one of {settings.SUPPORTED_MODELS}"
- )
- return value
- class BatchProductRequestSerializer(serializers.Serializer):
- """Serializer for batch product extraction request (with item-specific attributes)."""
- products = serializers.ListField(
- child=ProductBatchInputSerializer(),
- required=True,
- min_length=1
- )
- model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
- extract_additional = serializers.BooleanField(required=False, default=True)
- process_image = serializers.BooleanField(required=False, default=True)
- multiple = serializers.ListField(
- child=serializers.CharField(),
- required=False,
- default=list,
- help_text="List of attribute names that can have multiple values"
- )
- threshold_abs = serializers.FloatField(default=0.65, required=False)
- margin = serializers.FloatField(default=0.15, required=False)
- use_dynamic_thresholds = serializers.BooleanField(default=True, required=False)
- use_adaptive_margin = serializers.BooleanField(default=True, required=False)
- use_semantic_clustering = serializers.BooleanField(default=True, required=False)
-
- def validate_model(self, value):
- from django.conf import settings
- if value not in settings.SUPPORTED_MODELS:
- raise serializers.ValidationError(
- f"Model must be one of {settings.SUPPORTED_MODELS}"
- )
- return value
-
- def validate_products(self, value):
- from django.conf import settings
- max_size = getattr(settings, 'MAX_BATCH_SIZE', 100)
- if len(value) > max_size:
- raise serializers.ValidationError(
- f"Batch size cannot exceed {max_size} products"
- )
- return value
- class OCRResultSerializer(serializers.Serializer):
- """Serializer for OCR results."""
- detected_text = serializers.ListField(child=serializers.DictField())
- extracted_attributes = serializers.DictField()
- class VisualAttributeDetailSerializer(serializers.Serializer):
- """Serializer for detailed visual attribute predictions."""
- attribute = serializers.CharField()
- predictions = serializers.ListField(child=serializers.DictField())
- class VisualResultSerializer(serializers.Serializer):
- """Serializer for visual processing results."""
- visual_attributes = serializers.DictField(
- help_text="Extracted visual attributes like color, pattern, style, etc."
- )
- detailed_predictions = serializers.DictField(
- child=VisualAttributeDetailSerializer(),
- required=False,
- help_text="Detailed predictions with confidence scores for each attribute"
- )
- error = serializers.CharField(required=False)
- class ProductAttributeResultSerializer(serializers.Serializer):
- """Serializer for individual product extraction result."""
- product_id = serializers.CharField(required=False)
- mandatory = serializers.DictField()
- additional = serializers.DictField(required=False)
- ocr_results = OCRResultSerializer(required=False)
- visual_results = VisualResultSerializer(required=False)
- error = serializers.CharField(required=False)
- raw_output = serializers.CharField(required=False)
- class BatchProductResponseSerializer(serializers.Serializer):
- """Serializer for batch extraction response."""
- results = serializers.ListField(child=ProductAttributeResultSerializer())
- total_products = serializers.IntegerField()
- successful = serializers.IntegerField()
- failed = serializers.IntegerField()
- class ProductSerializer(serializers.ModelSerializer):
- """Serializer for Product model with product type details."""
- product_type_details = serializers.SerializerMethodField()
-
- class Meta:
- model = Product
- fields = [
- 'id',
- 'item_id',
- 'product_name',
- 'product_long_description',
- 'product_short_description',
- 'product_type',
- 'image_path',
- 'image',
- 'product_type_details',
- ]
- def get_product_type_details(self, obj):
- """Fetch ProductType object and its attributes for this product."""
- try:
- product_type = ProductType.objects.get(name=obj.product_type)
- except ProductType.DoesNotExist:
- return []
- # Serialize its attributes
- attributes = ProductAttribute.objects.filter(product_type=product_type)
- return [
- {
- "attribute_name": attr.name,
- "is_mandatory": "Yes" if attr.is_mandatory else "No",
- "possible_values": [pv.value for pv in attr.possible_values.all()]
- }
- for attr in attributes
- ]
- class AttributePossibleValueSerializer(serializers.ModelSerializer):
- """Serializer for AttributePossibleValue model."""
- class Meta:
- model = AttributePossibleValue
- fields = ['value']
- class ProductAttributeSerializer(serializers.ModelSerializer):
- """Serializer for ProductAttribute model with possible values."""
- possible_values = AttributePossibleValueSerializer(many=True, read_only=True)
-
- class Meta:
- model = ProductAttribute
- fields = ['name', 'is_mandatory', 'possible_values']
- class ProductTypeSerializer(serializers.ModelSerializer):
- """Serializer for ProductType model with attributes."""
- attributes = ProductAttributeSerializer(many=True, read_only=True)
-
- class Meta:
- model = ProductType
- fields = ['name', 'attributes']
- # Add these new serializers to your serializers.py
- from rest_framework import serializers
- from .models import Product, ProductType, ProductAttribute, AttributePossibleValue, ProductAttributeValue
- class ProductAttributeValueSerializer(serializers.ModelSerializer):
- """Serializer for manually entered attribute values."""
- item_id = serializers.CharField(source='product.item_id', read_only=True)
-
- class Meta:
- model = ProductAttributeValue
- fields = ['id', 'item_id', 'attribute_name', 'original_value', 'created_at', 'updated_at']
- read_only_fields = ['created_at', 'updated_at']
- class ProductAttributeValueInputSerializer(serializers.Serializer):
- """Serializer for creating/updating attribute values."""
- item_id = serializers.CharField(required=True)
- attribute_name = serializers.CharField(required=True)
- original_value = serializers.CharField(required=True, allow_blank=True)
- class BulkProductAttributeValueSerializer(serializers.Serializer):
- """Serializer for bulk upload of attribute values."""
- item_id = serializers.CharField(required=True)
- attributes = serializers.DictField(
- child=serializers.CharField(allow_blank=True),
- required=True,
- help_text="Dictionary of attribute_name: original_value pairs"
- )
- class ProductWithAttributesSerializer(serializers.ModelSerializer):
- """Extended Product serializer with original attribute values."""
- product_type_details = serializers.SerializerMethodField()
- original_attributes = serializers.SerializerMethodField()
-
- class Meta:
- model = Product
- fields = [
- 'id',
- 'item_id',
- 'product_name',
- 'product_long_description',
- 'product_short_description',
- 'product_type',
- 'image_path',
- 'image',
- 'product_type_details',
- 'original_attributes',
- ]
- def get_product_type_details(self, obj):
- """Fetch ProductType object and its attributes for this product."""
- try:
- product_type = ProductType.objects.get(name=obj.product_type)
- except ProductType.DoesNotExist:
- return []
- attributes = ProductAttribute.objects.filter(product_type=product_type)
- return [
- {
- "attribute_name": attr.name,
- "is_mandatory": "Yes" if attr.is_mandatory else "No",
- "possible_values": [pv.value for pv in attr.possible_values.all()]
- }
- for attr in attributes
- ]
-
- def get_original_attributes(self, obj):
- """Get manually entered original attribute values."""
- values = ProductAttributeValue.objects.filter(product=obj)
- return {val.attribute_name: val.original_value for val in values}
|