In my code ServiceListSerializer(many=True, source='service_id')
is giving all the services list, instead of services according to its category
I have no idea how to retrieve and filter from manytomany field
Heres my code:
Models.py
class Services(models.Model):
service_id = models.AutoField(primary_key=True)
parent_id = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True,related_name='sub_service')
service_name = models.CharField(max_length=100)
service_icon = models.CharField(max_length=500, null=True, blank=True)
service_image = models.CharField(max_length=500, null=True, blank=True)
service_description = models.CharField(max_length=5000, null=True, blank=True)
category_id = models.ForeignKey(Category,on_delete=models.CASCADE)
active_status = models.BooleanField(default=True)
type = models.SmallIntegerField(blank=True, null=True)
class Variant(models.Model):
variant_id = models.AutoField(primary_key=True)
service_id = models.ManyToManyField(Services)
category_id = models.ManyToManyField(Category)
variant_name = models.CharField(max_length=100)
variant_icon = models.CharField(max_length=1000, null=True, blank=True)
variant_image = models.CharField(max_length=1000, null=True, blank=True)
variant_description = models.CharField(max_length=5000, null=True, blank=True)
active_status = models.BooleanField(default=True)
View.py
class ServicesList(viewsets.ViewSet):
def list(self, request):
variant_id = request.data.get('variant_id')
queryset = Category.objects.all()
querysetSerializer = CategoryServiceListSerializer(queryset, many=True, context={'variant_id': variant_id})
return Response({"status": 200, "message": "Success", "data": querysetSerializer.data})
Serializer.py
class CategoryServiceListSerializer(serializers.ModelSerializer):
variant = serializers.SerializerMethodField()
def get_variant(self, instance):
variant_id = self.context.get('variant_id')
if variant_id:
variants = instance.variant_set.filter(pk=variant_id)
else:
variants = instance.variant_set.all()
return VariantServiceSerializer(variants, many=True).data
class Meta:
fields = ("category_id", "category_name", "category_icon", "category_description", "variant")
model = Category
class ServiceListSerializer(serializers.ModelSerializer):
class Meta:
model = Services
fields = "__all__"
class VariantServiceSerializer(serializers.ModelSerializer):
services = ServiceListSerializer(many=True, source='service_id')
# services = serializers.SerializerMethodField()
class Meta:
model = Variant
fields = "__all__"
# def get_services(self, obj):
# print(obj.service_id)
# return obj
Output:
{
"category_id": 1, # <
"category_name": "category1",
"variant": [
{
"variant_id": 2,
"variant_name": "variant2",
"services": [
{
"service_id": 2,
"service_name": "service2",
"category_id": 1
},
{
"service_id": 1,
"service_name": "service1",
"category_id": 1
},
{
"service_id": 1,
"service_name": "service1",
"category_id": 2 #Category Not match with parent
}
]
}
]
},
{
"category_id": 2, # <
"category_name": "categoy2",
"variant": [
{
"variant_id": 2,
"variant_name": "variant2",
"services": [
{
"service_id": 2,
"service_name": "service2",
"category_id": 1 #Category Not match with parent
},
{
"service_id": 1,
"service_name": "service1",
"category_id": 1 #Category Not match with parent
},
{
"service_id": 1,
"service_name": "service1",
"category_id": 2
}
]
}
]
},
{
"category_id": 3, # <
"category_name": "category3",
"variant": [
{
"variant_id": 2,
"variant_name": "variant2",
"services": [
{
"service_id": 2,
"service_name": "service2",
"category_id": 1 #Category Not match with parent
},
{
"service_id": 1,
"service_name": "service1",
"category_id": 1 #Category Not match with parent
},
{
"service_id": 1,
"service_name": "service1",
"category_id": 2 #Category Not match with parent
}
]
}
]
}
Expected Output:
{
"category_id": 1,
"category_name": "category1",
"variant": [
{
"variant_id": 2,
"variant_name": "variant2",
"services": [
{
"service_id": 2,
"service_name": "service2",
"category_id": 1
},
{
"service_id": 1,
"service_name": "service1",
"category_id": 1
}
]
}
]
},
{
"category_id": 2,
"category_name": "categoy2",
"variant": [
{
"variant_id": 2,
"variant_name": "variant2",
"services": [
{
"service_id": 1,
"service_name": "service1",
"category_id": 2
}
]
}
]
},
{
"category_id": 3,
"category_name": "category3",
"variant": [
{
"variant_id": 2,
"variant_name": "variant2",
"services": []
}
]
}
CodePudding user response:
Try to Prefetch
the related services of a variant and filter only with the matching category based on the category instance like this:
class CategoryServiceListSerializer(serializers.ModelSerializer):
variant = serializers.SerializerMethodField()
def get_variant(self, instance):
variant_id = self.context.get('variant_id')
if variant_id:
variants = instance.variant_set.filter(pk=variant_id)
else:
variants = instance.variant_set.all()
variants = variants.prefetch_related(
Prefetch(
'services'
queryset=Services.objects.filter(category_id=instance.category_id)
)
)
return VariantServiceSerializer(variants, many=True).data