serializers.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. # # ==================== serializers.py ====================
  2. # from rest_framework import serializers
  3. # class ProductInputSerializer(serializers.Serializer):
  4. # """Serializer for individual product input."""
  5. # product_id = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  6. # title = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  7. # short_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  8. # long_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  9. # image_url = serializers.URLField(required=False, allow_blank=True, allow_null=True)
  10. # class MandatoryAttrsField(serializers.DictField):
  11. # """Custom DictField to validate mandatory_attrs structure."""
  12. # child = serializers.ListField(child=serializers.CharField())
  13. # class ProductBatchInputSerializer(serializers.Serializer):
  14. # """Serializer for an individual product input within the batch request."""
  15. # item_id = serializers.CharField(required=True)
  16. # mandatory_attrs = MandatoryAttrsField(
  17. # required=True,
  18. # help_text="A dictionary of attribute names and their possible values."
  19. # )
  20. # # You can also allow per-product model/flags if needed, but keeping it batch-level for simplicity here.
  21. # class SingleProductRequestSerializer(serializers.Serializer):
  22. # """Serializer for single product extraction request."""
  23. # # title = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  24. # # short_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  25. # # long_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  26. # # image_url = serializers.URLField(required=False, allow_blank=True, allow_null=True)
  27. # item_id = serializers.CharField(required=True)
  28. # mandatory_attrs = serializers.DictField(
  29. # child=serializers.ListField(child=serializers.CharField()),
  30. # required=True
  31. # )
  32. # model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
  33. # extract_additional = serializers.BooleanField(required=False, default=True)
  34. # process_image = serializers.BooleanField(required=False, default=True)
  35. # def validate_model(self, value):
  36. # from django.conf import settings
  37. # if value not in settings.SUPPORTED_MODELS:
  38. # raise serializers.ValidationError(
  39. # f"Model must be one of {settings.SUPPORTED_MODELS}"
  40. # )
  41. # return value
  42. # class BatchProductRequestSerializer(serializers.Serializer):
  43. # """Serializer for batch product extraction request (with item-specific attributes)."""
  44. # products = serializers.ListField(
  45. # child=ProductBatchInputSerializer(), # <--- Changed
  46. # required=True,
  47. # min_length=1
  48. # )
  49. # model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
  50. # extract_additional = serializers.BooleanField(required=False, default=True)
  51. # process_image = serializers.BooleanField(required=False, default=True)
  52. # # ... validate_model method ...
  53. # def validate_model(self, value):
  54. # from django.conf import settings
  55. # if value not in settings.SUPPORTED_MODELS:
  56. # raise serializers.ValidationError(
  57. # f"Model must be one of {settings.SUPPORTED_MODELS}"
  58. # )
  59. # return value
  60. # # ... validate_products method (updated to use products instead of item_ids) ...
  61. # def validate_products(self, value):
  62. # from django.conf import settings
  63. # max_size = getattr(settings, 'MAX_BATCH_SIZE', 100)
  64. # if len(value) > max_size:
  65. # raise serializers.ValidationError(
  66. # f"Batch size cannot exceed {max_size} products"
  67. # )
  68. # return value
  69. # class OCRResultSerializer(serializers.Serializer):
  70. # """Serializer for OCR results."""
  71. # detected_text = serializers.ListField(child=serializers.DictField())
  72. # extracted_attributes = serializers.DictField()
  73. # class ProductAttributeResultSerializer(serializers.Serializer):
  74. # """Serializer for individual product extraction result."""
  75. # product_id = serializers.CharField(required=False)
  76. # mandatory = serializers.DictField()
  77. # additional = serializers.DictField(required=False)
  78. # ocr_results = OCRResultSerializer(required=False)
  79. # error = serializers.CharField(required=False)
  80. # raw_output = serializers.CharField(required=False)
  81. # class BatchProductResponseSerializer(serializers.Serializer):
  82. # """Serializer for batch extraction response."""
  83. # results = serializers.ListField(child=ProductAttributeResultSerializer())
  84. # total_products = serializers.IntegerField()
  85. # successful = serializers.IntegerField()
  86. # failed = serializers.IntegerField()
  87. # from rest_framework import serializers
  88. # from .models import Product
  89. # class ProductSerializer(serializers.ModelSerializer):
  90. # product_type_details = serializers.SerializerMethodField()
  91. # class Meta:
  92. # model = Product
  93. # fields = [
  94. # 'id',
  95. # 'item_id',
  96. # 'product_name',
  97. # 'product_long_description',
  98. # 'product_short_description',
  99. # 'product_type',
  100. # 'image_path',
  101. # 'image',
  102. # 'product_type_details', # new field
  103. # ]
  104. # def get_product_type_details(self, obj):
  105. # # Fetch ProductType object for this product
  106. # try:
  107. # product_type = ProductType.objects.get(name=obj.product_type)
  108. # except ProductType.DoesNotExist:
  109. # return []
  110. # # Serialize its attributes
  111. # attributes = ProductAttribute.objects.filter(product_type=product_type)
  112. # return [
  113. # {
  114. # "attribute_name": attr.name,
  115. # "is_mandatory": "Yes" if attr.is_mandatory else "No",
  116. # "possible_values": [pv.value for pv in attr.possible_values.all()]
  117. # }
  118. # for attr in attributes
  119. # ]
  120. # from rest_framework import serializers
  121. # from .models import Product, ProductType, ProductAttribute, AttributePossibleValue
  122. # class AttributePossibleValueSerializer(serializers.ModelSerializer):
  123. # class Meta:
  124. # model = AttributePossibleValue
  125. # fields = ['value']
  126. # class ProductAttributeSerializer(serializers.ModelSerializer):
  127. # possible_values = AttributePossibleValueSerializer(many=True, read_only=True)
  128. # class Meta:
  129. # model = ProductAttribute
  130. # fields = ['name', 'is_mandatory', 'possible_values']
  131. # class ProductTypeSerializer(serializers.ModelSerializer):
  132. # attributes = ProductAttributeSerializer(many=True, read_only=True)
  133. # class Meta:
  134. # model = ProductType
  135. # fields = ['name', 'attributes']
  136. # ==================== serializers.py ====================
  137. from rest_framework import serializers
  138. from .models import Product, ProductType, ProductAttribute, AttributePossibleValue
  139. class ProductInputSerializer(serializers.Serializer):
  140. """Serializer for individual product input."""
  141. product_id = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  142. title = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  143. short_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  144. long_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  145. image_url = serializers.URLField(required=False, allow_blank=True, allow_null=True)
  146. class MandatoryAttrsField(serializers.DictField):
  147. """Custom DictField to validate mandatory_attrs structure."""
  148. child = serializers.ListField(child=serializers.CharField())
  149. class ProductBatchInputSerializer(serializers.Serializer):
  150. """Serializer for an individual product input within the batch request."""
  151. item_id = serializers.CharField(required=True)
  152. mandatory_attrs = MandatoryAttrsField(
  153. required=True,
  154. help_text="A dictionary of attribute names and their possible values."
  155. )
  156. class SingleProductRequestSerializer(serializers.Serializer):
  157. """Serializer for single product extraction request."""
  158. item_id = serializers.CharField(required=True)
  159. mandatory_attrs = serializers.DictField(
  160. child=serializers.ListField(child=serializers.CharField()),
  161. required=True
  162. )
  163. model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
  164. extract_additional = serializers.BooleanField(required=False, default=True)
  165. process_image = serializers.BooleanField(required=False, default=True)
  166. multiple = serializers.ListField(
  167. child=serializers.CharField(),
  168. required=False,
  169. default=list,
  170. help_text="List of attribute names that can have multiple values"
  171. )
  172. threshold_abs = serializers.FloatField(default=0.65, required=False)
  173. margin = serializers.FloatField(default=0.15, required=False)
  174. use_dynamic_thresholds = serializers.BooleanField(default=True, required=False)
  175. use_adaptive_margin = serializers.BooleanField(default=True, required=False)
  176. use_semantic_clustering = serializers.BooleanField(default=True, required=False)
  177. def validate_model(self, value):
  178. from django.conf import settings
  179. if value not in settings.SUPPORTED_MODELS:
  180. raise serializers.ValidationError(
  181. f"Model must be one of {settings.SUPPORTED_MODELS}"
  182. )
  183. return value
  184. class BatchProductRequestSerializer(serializers.Serializer):
  185. """Serializer for batch product extraction request (with item-specific attributes)."""
  186. products = serializers.ListField(
  187. child=ProductBatchInputSerializer(),
  188. required=True,
  189. min_length=1
  190. )
  191. model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
  192. extract_additional = serializers.BooleanField(required=False, default=True)
  193. process_image = serializers.BooleanField(required=False, default=True)
  194. multiple = serializers.ListField(
  195. child=serializers.CharField(),
  196. required=False,
  197. default=list,
  198. help_text="List of attribute names that can have multiple values"
  199. )
  200. threshold_abs = serializers.FloatField(default=0.65, required=False)
  201. margin = serializers.FloatField(default=0.15, required=False)
  202. use_dynamic_thresholds = serializers.BooleanField(default=True, required=False)
  203. use_adaptive_margin = serializers.BooleanField(default=True, required=False)
  204. use_semantic_clustering = serializers.BooleanField(default=True, required=False)
  205. def validate_model(self, value):
  206. from django.conf import settings
  207. if value not in settings.SUPPORTED_MODELS:
  208. raise serializers.ValidationError(
  209. f"Model must be one of {settings.SUPPORTED_MODELS}"
  210. )
  211. return value
  212. def validate_products(self, value):
  213. from django.conf import settings
  214. max_size = getattr(settings, 'MAX_BATCH_SIZE', 100)
  215. if len(value) > max_size:
  216. raise serializers.ValidationError(
  217. f"Batch size cannot exceed {max_size} products"
  218. )
  219. return value
  220. class OCRResultSerializer(serializers.Serializer):
  221. """Serializer for OCR results."""
  222. detected_text = serializers.ListField(child=serializers.DictField())
  223. extracted_attributes = serializers.DictField()
  224. class ProductAttributeResultSerializer(serializers.Serializer):
  225. """Serializer for individual product extraction result."""
  226. product_id = serializers.CharField(required=False)
  227. mandatory = serializers.DictField()
  228. additional = serializers.DictField(required=False)
  229. ocr_results = OCRResultSerializer(required=False)
  230. error = serializers.CharField(required=False)
  231. raw_output = serializers.CharField(required=False)
  232. class BatchProductResponseSerializer(serializers.Serializer):
  233. """Serializer for batch extraction response."""
  234. results = serializers.ListField(child=ProductAttributeResultSerializer())
  235. total_products = serializers.IntegerField()
  236. successful = serializers.IntegerField()
  237. failed = serializers.IntegerField()
  238. class ProductSerializer(serializers.ModelSerializer):
  239. """Serializer for Product model with product type details."""
  240. product_type_details = serializers.SerializerMethodField()
  241. class Meta:
  242. model = Product
  243. fields = [
  244. 'id',
  245. 'item_id',
  246. 'product_name',
  247. 'product_long_description',
  248. 'product_short_description',
  249. 'product_type',
  250. 'image_path',
  251. 'image',
  252. 'product_type_details',
  253. ]
  254. def get_product_type_details(self, obj):
  255. """Fetch ProductType object and its attributes for this product."""
  256. try:
  257. product_type = ProductType.objects.get(name=obj.product_type)
  258. except ProductType.DoesNotExist:
  259. return []
  260. # Serialize its attributes
  261. attributes = ProductAttribute.objects.filter(product_type=product_type)
  262. return [
  263. {
  264. "attribute_name": attr.name,
  265. "is_mandatory": "Yes" if attr.is_mandatory else "No",
  266. "possible_values": [pv.value for pv in attr.possible_values.all()]
  267. }
  268. for attr in attributes
  269. ]
  270. class AttributePossibleValueSerializer(serializers.ModelSerializer):
  271. """Serializer for AttributePossibleValue model."""
  272. class Meta:
  273. model = AttributePossibleValue
  274. fields = ['value']
  275. class ProductAttributeSerializer(serializers.ModelSerializer):
  276. """Serializer for ProductAttribute model with possible values."""
  277. possible_values = AttributePossibleValueSerializer(many=True, read_only=True)
  278. class Meta:
  279. model = ProductAttribute
  280. fields = ['name', 'is_mandatory', 'possible_values']
  281. class ProductTypeSerializer(serializers.ModelSerializer):
  282. """Serializer for ProductType model with attributes."""
  283. attributes = ProductAttributeSerializer(many=True, read_only=True)
  284. class Meta:
  285. model = ProductType
  286. fields = ['name', 'attributes']