serializers.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. # # ==================== serializers.py ====================
  2. # from rest_framework import serializers
  3. # from .models import Product, ProductType, ProductAttribute, AttributePossibleValue
  4. # class ProductInputSerializer(serializers.Serializer):
  5. # """Serializer for individual product input."""
  6. # product_id = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  7. # title = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  8. # short_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  9. # long_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  10. # image_url = serializers.URLField(required=False, allow_blank=True, allow_null=True)
  11. # class MandatoryAttrsField(serializers.DictField):
  12. # """Custom DictField to validate mandatory_attrs structure."""
  13. # child = serializers.ListField(child=serializers.CharField())
  14. # class ProductBatchInputSerializer(serializers.Serializer):
  15. # """Serializer for an individual product input within the batch request."""
  16. # item_id = serializers.CharField(required=True)
  17. # mandatory_attrs = MandatoryAttrsField(
  18. # required=True,
  19. # help_text="A dictionary of attribute names and their possible values."
  20. # )
  21. # class SingleProductRequestSerializer(serializers.Serializer):
  22. # """Serializer for single product extraction request."""
  23. # item_id = serializers.CharField(required=True)
  24. # mandatory_attrs = serializers.DictField(
  25. # child=serializers.ListField(child=serializers.CharField()),
  26. # required=True
  27. # )
  28. # model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
  29. # extract_additional = serializers.BooleanField(required=False, default=True)
  30. # process_image = serializers.BooleanField(required=False, default=True)
  31. # multiple = serializers.ListField(
  32. # child=serializers.CharField(),
  33. # required=False,
  34. # default=list,
  35. # help_text="List of attribute names that can have multiple values"
  36. # )
  37. # threshold_abs = serializers.FloatField(default=0.65, required=False)
  38. # margin = serializers.FloatField(default=0.15, required=False)
  39. # use_dynamic_thresholds = serializers.BooleanField(default=True, required=False)
  40. # use_adaptive_margin = serializers.BooleanField(default=True, required=False)
  41. # use_semantic_clustering = serializers.BooleanField(default=True, required=False)
  42. # def validate_model(self, value):
  43. # from django.conf import settings
  44. # if value not in settings.SUPPORTED_MODELS:
  45. # raise serializers.ValidationError(
  46. # f"Model must be one of {settings.SUPPORTED_MODELS}"
  47. # )
  48. # return value
  49. # class BatchProductRequestSerializer(serializers.Serializer):
  50. # """Serializer for batch product extraction request (with item-specific attributes)."""
  51. # products = serializers.ListField(
  52. # child=ProductBatchInputSerializer(),
  53. # required=True,
  54. # min_length=1
  55. # )
  56. # model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
  57. # extract_additional = serializers.BooleanField(required=False, default=True)
  58. # process_image = serializers.BooleanField(required=False, default=True)
  59. # multiple = serializers.ListField(
  60. # child=serializers.CharField(),
  61. # required=False,
  62. # default=list,
  63. # help_text="List of attribute names that can have multiple values"
  64. # )
  65. # threshold_abs = serializers.FloatField(default=0.65, required=False)
  66. # margin = serializers.FloatField(default=0.15, required=False)
  67. # use_dynamic_thresholds = serializers.BooleanField(default=True, required=False)
  68. # use_adaptive_margin = serializers.BooleanField(default=True, required=False)
  69. # use_semantic_clustering = serializers.BooleanField(default=True, required=False)
  70. # def validate_model(self, value):
  71. # from django.conf import settings
  72. # if value not in settings.SUPPORTED_MODELS:
  73. # raise serializers.ValidationError(
  74. # f"Model must be one of {settings.SUPPORTED_MODELS}"
  75. # )
  76. # return value
  77. # def validate_products(self, value):
  78. # from django.conf import settings
  79. # max_size = getattr(settings, 'MAX_BATCH_SIZE', 100)
  80. # if len(value) > max_size:
  81. # raise serializers.ValidationError(
  82. # f"Batch size cannot exceed {max_size} products"
  83. # )
  84. # return value
  85. # class OCRResultSerializer(serializers.Serializer):
  86. # """Serializer for OCR results."""
  87. # detected_text = serializers.ListField(child=serializers.DictField())
  88. # extracted_attributes = serializers.DictField()
  89. # class ProductAttributeResultSerializer(serializers.Serializer):
  90. # """Serializer for individual product extraction result."""
  91. # product_id = serializers.CharField(required=False)
  92. # mandatory = serializers.DictField()
  93. # additional = serializers.DictField(required=False)
  94. # ocr_results = OCRResultSerializer(required=False)
  95. # error = serializers.CharField(required=False)
  96. # raw_output = serializers.CharField(required=False)
  97. # class BatchProductResponseSerializer(serializers.Serializer):
  98. # """Serializer for batch extraction response."""
  99. # results = serializers.ListField(child=ProductAttributeResultSerializer())
  100. # total_products = serializers.IntegerField()
  101. # successful = serializers.IntegerField()
  102. # failed = serializers.IntegerField()
  103. # class ProductSerializer(serializers.ModelSerializer):
  104. # """Serializer for Product model with product type details."""
  105. # product_type_details = serializers.SerializerMethodField()
  106. # class Meta:
  107. # model = Product
  108. # fields = [
  109. # 'id',
  110. # 'item_id',
  111. # 'product_name',
  112. # 'product_long_description',
  113. # 'product_short_description',
  114. # 'product_type',
  115. # 'image_path',
  116. # 'image',
  117. # 'product_type_details',
  118. # ]
  119. # def get_product_type_details(self, obj):
  120. # """Fetch ProductType object and its attributes for this product."""
  121. # try:
  122. # product_type = ProductType.objects.get(name=obj.product_type)
  123. # except ProductType.DoesNotExist:
  124. # return []
  125. # # Serialize its attributes
  126. # attributes = ProductAttribute.objects.filter(product_type=product_type)
  127. # return [
  128. # {
  129. # "attribute_name": attr.name,
  130. # "is_mandatory": "Yes" if attr.is_mandatory else "No",
  131. # "possible_values": [pv.value for pv in attr.possible_values.all()]
  132. # }
  133. # for attr in attributes
  134. # ]
  135. # class AttributePossibleValueSerializer(serializers.ModelSerializer):
  136. # """Serializer for AttributePossibleValue model."""
  137. # class Meta:
  138. # model = AttributePossibleValue
  139. # fields = ['value']
  140. # class ProductAttributeSerializer(serializers.ModelSerializer):
  141. # """Serializer for ProductAttribute model with possible values."""
  142. # possible_values = AttributePossibleValueSerializer(many=True, read_only=True)
  143. # class Meta:
  144. # model = ProductAttribute
  145. # fields = ['name', 'is_mandatory', 'possible_values']
  146. # class ProductTypeSerializer(serializers.ModelSerializer):
  147. # """Serializer for ProductType model with attributes."""
  148. # attributes = ProductAttributeSerializer(many=True, read_only=True)
  149. # class Meta:
  150. # model = ProductType
  151. # fields = ['name', 'attributes']
  152. # ==================== Updated serializers.py ====================
  153. from rest_framework import serializers
  154. from .models import Product, ProductType, ProductAttribute, AttributePossibleValue
  155. class ProductInputSerializer(serializers.Serializer):
  156. """Serializer for individual product input."""
  157. product_id = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  158. title = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  159. short_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  160. long_desc = serializers.CharField(required=False, allow_blank=True, allow_null=True)
  161. image_url = serializers.URLField(required=False, allow_blank=True, allow_null=True)
  162. class MandatoryAttrsField(serializers.DictField):
  163. """Custom DictField to validate mandatory_attrs structure."""
  164. child = serializers.ListField(child=serializers.CharField())
  165. class ProductBatchInputSerializer(serializers.Serializer):
  166. """Serializer for an individual product input within the batch request."""
  167. item_id = serializers.CharField(required=True)
  168. mandatory_attrs = MandatoryAttrsField(
  169. required=True,
  170. help_text="A dictionary of attribute names and their possible values."
  171. )
  172. class SingleProductRequestSerializer(serializers.Serializer):
  173. """Serializer for single product extraction request."""
  174. item_id = serializers.CharField(required=True)
  175. mandatory_attrs = serializers.DictField(
  176. child=serializers.ListField(child=serializers.CharField()),
  177. required=True
  178. )
  179. model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
  180. extract_additional = serializers.BooleanField(required=False, default=True)
  181. process_image = serializers.BooleanField(required=False, default=True)
  182. multiple = serializers.ListField(
  183. child=serializers.CharField(),
  184. required=False,
  185. default=list,
  186. help_text="List of attribute names that can have multiple values"
  187. )
  188. threshold_abs = serializers.FloatField(default=0.65, required=False)
  189. margin = serializers.FloatField(default=0.15, required=False)
  190. use_dynamic_thresholds = serializers.BooleanField(default=True, required=False)
  191. use_adaptive_margin = serializers.BooleanField(default=True, required=False)
  192. use_semantic_clustering = serializers.BooleanField(default=True, required=False)
  193. def validate_model(self, value):
  194. from django.conf import settings
  195. if value not in settings.SUPPORTED_MODELS:
  196. raise serializers.ValidationError(
  197. f"Model must be one of {settings.SUPPORTED_MODELS}"
  198. )
  199. return value
  200. class BatchProductRequestSerializer(serializers.Serializer):
  201. """Serializer for batch product extraction request (with item-specific attributes)."""
  202. products = serializers.ListField(
  203. child=ProductBatchInputSerializer(),
  204. required=True,
  205. min_length=1
  206. )
  207. model = serializers.CharField(required=False, default="llama-3.1-8b-instant")
  208. extract_additional = serializers.BooleanField(required=False, default=True)
  209. process_image = serializers.BooleanField(required=False, default=True)
  210. multiple = serializers.ListField(
  211. child=serializers.CharField(),
  212. required=False,
  213. default=list,
  214. help_text="List of attribute names that can have multiple values"
  215. )
  216. threshold_abs = serializers.FloatField(default=0.65, required=False)
  217. margin = serializers.FloatField(default=0.15, required=False)
  218. use_dynamic_thresholds = serializers.BooleanField(default=True, required=False)
  219. use_adaptive_margin = serializers.BooleanField(default=True, required=False)
  220. use_semantic_clustering = serializers.BooleanField(default=True, required=False)
  221. def validate_model(self, value):
  222. from django.conf import settings
  223. if value not in settings.SUPPORTED_MODELS:
  224. raise serializers.ValidationError(
  225. f"Model must be one of {settings.SUPPORTED_MODELS}"
  226. )
  227. return value
  228. def validate_products(self, value):
  229. from django.conf import settings
  230. max_size = getattr(settings, 'MAX_BATCH_SIZE', 100)
  231. if len(value) > max_size:
  232. raise serializers.ValidationError(
  233. f"Batch size cannot exceed {max_size} products"
  234. )
  235. return value
  236. class OCRResultSerializer(serializers.Serializer):
  237. """Serializer for OCR results."""
  238. detected_text = serializers.ListField(child=serializers.DictField())
  239. extracted_attributes = serializers.DictField()
  240. class VisualAttributeDetailSerializer(serializers.Serializer):
  241. """Serializer for detailed visual attribute predictions."""
  242. attribute = serializers.CharField()
  243. predictions = serializers.ListField(child=serializers.DictField())
  244. class VisualResultSerializer(serializers.Serializer):
  245. """Serializer for visual processing results."""
  246. visual_attributes = serializers.DictField(
  247. help_text="Extracted visual attributes like color, pattern, style, etc."
  248. )
  249. detailed_predictions = serializers.DictField(
  250. child=VisualAttributeDetailSerializer(),
  251. required=False,
  252. help_text="Detailed predictions with confidence scores for each attribute"
  253. )
  254. error = serializers.CharField(required=False)
  255. class ProductAttributeResultSerializer(serializers.Serializer):
  256. """Serializer for individual product extraction result."""
  257. product_id = serializers.CharField(required=False)
  258. mandatory = serializers.DictField()
  259. additional = serializers.DictField(required=False)
  260. ocr_results = OCRResultSerializer(required=False)
  261. visual_results = VisualResultSerializer(required=False)
  262. error = serializers.CharField(required=False)
  263. raw_output = serializers.CharField(required=False)
  264. class BatchProductResponseSerializer(serializers.Serializer):
  265. """Serializer for batch extraction response."""
  266. results = serializers.ListField(child=ProductAttributeResultSerializer())
  267. total_products = serializers.IntegerField()
  268. successful = serializers.IntegerField()
  269. failed = serializers.IntegerField()
  270. class ProductSerializer(serializers.ModelSerializer):
  271. """Serializer for Product model with product type details."""
  272. product_type_details = serializers.SerializerMethodField()
  273. class Meta:
  274. model = Product
  275. fields = [
  276. 'id',
  277. 'item_id',
  278. 'product_name',
  279. 'product_long_description',
  280. 'product_short_description',
  281. 'product_type',
  282. 'image_path',
  283. 'image',
  284. 'product_type_details',
  285. ]
  286. def get_product_type_details(self, obj):
  287. """Fetch ProductType object and its attributes for this product."""
  288. try:
  289. product_type = ProductType.objects.get(name=obj.product_type)
  290. except ProductType.DoesNotExist:
  291. return []
  292. # Serialize its attributes
  293. attributes = ProductAttribute.objects.filter(product_type=product_type)
  294. return [
  295. {
  296. "attribute_name": attr.name,
  297. "is_mandatory": "Yes" if attr.is_mandatory else "No",
  298. "possible_values": [pv.value for pv in attr.possible_values.all()]
  299. }
  300. for attr in attributes
  301. ]
  302. class AttributePossibleValueSerializer(serializers.ModelSerializer):
  303. """Serializer for AttributePossibleValue model."""
  304. class Meta:
  305. model = AttributePossibleValue
  306. fields = ['value']
  307. class ProductAttributeSerializer(serializers.ModelSerializer):
  308. """Serializer for ProductAttribute model with possible values."""
  309. possible_values = AttributePossibleValueSerializer(many=True, read_only=True)
  310. class Meta:
  311. model = ProductAttribute
  312. fields = ['name', 'is_mandatory', 'possible_values']
  313. class ProductTypeSerializer(serializers.ModelSerializer):
  314. """Serializer for ProductType model with attributes."""
  315. attributes = ProductAttributeSerializer(many=True, read_only=True)
  316. class Meta:
  317. model = ProductType
  318. fields = ['name', 'attributes']
  319. # Add these new serializers to your serializers.py
  320. from rest_framework import serializers
  321. from .models import Product, ProductType, ProductAttribute, AttributePossibleValue, ProductAttributeValue
  322. class ProductAttributeValueSerializer(serializers.ModelSerializer):
  323. """Serializer for manually entered attribute values."""
  324. item_id = serializers.CharField(source='product.item_id', read_only=True)
  325. class Meta:
  326. model = ProductAttributeValue
  327. fields = ['id', 'item_id', 'attribute_name', 'original_value', 'created_at', 'updated_at']
  328. read_only_fields = ['created_at', 'updated_at']
  329. class ProductAttributeValueInputSerializer(serializers.Serializer):
  330. """Serializer for creating/updating attribute values."""
  331. item_id = serializers.CharField(required=True)
  332. attribute_name = serializers.CharField(required=True)
  333. original_value = serializers.CharField(required=True, allow_blank=True)
  334. class BulkProductAttributeValueSerializer(serializers.Serializer):
  335. """Serializer for bulk upload of attribute values."""
  336. item_id = serializers.CharField(required=True)
  337. attributes = serializers.DictField(
  338. child=serializers.CharField(allow_blank=True),
  339. required=True,
  340. help_text="Dictionary of attribute_name: original_value pairs"
  341. )
  342. class ProductWithAttributesSerializer(serializers.ModelSerializer):
  343. """Extended Product serializer with original attribute values."""
  344. product_type_details = serializers.SerializerMethodField()
  345. original_attributes = serializers.SerializerMethodField()
  346. class Meta:
  347. model = Product
  348. fields = [
  349. 'id',
  350. 'item_id',
  351. 'product_name',
  352. 'product_long_description',
  353. 'product_short_description',
  354. 'product_type',
  355. 'image_path',
  356. 'image',
  357. 'product_type_details',
  358. 'original_attributes',
  359. ]
  360. def get_product_type_details(self, obj):
  361. """Fetch ProductType object and its attributes for this product."""
  362. try:
  363. product_type = ProductType.objects.get(name=obj.product_type)
  364. except ProductType.DoesNotExist:
  365. return []
  366. attributes = ProductAttribute.objects.filter(product_type=product_type)
  367. return [
  368. {
  369. "attribute_name": attr.name,
  370. "is_mandatory": "Yes" if attr.is_mandatory else "No",
  371. "possible_values": [pv.value for pv in attr.possible_values.all()]
  372. }
  373. for attr in attributes
  374. ]
  375. def get_original_attributes(self, obj):
  376. """Get manually entered original attribute values."""
  377. values = ProductAttributeValue.objects.filter(product=obj)
  378. return {val.attribute_name: val.original_value for val in values}