how do i filter from variant that is many_to_many relationship with category

Viewed 43

Here is my code:

# VIEW.PY
def retrieve(self, request, pk=None):
    variant_id = request.get('variant_id')
    queryset = Category.objects.filter(category_id=pk)
    querysetSerializer = CategoryServiceListSerializer(queryset, many=True)

i want to filter variant_id from Variant so that it display only that particular variuant. Not sure where changes need to be made in views or serialzier.

im assuming this could be solution

queryset = Category.objects.filter(category_id=pk,variant__in = variant_id) 

but getting error TypeError: 'int' object is not iterable

# MODELS.PY
class Category(models.Model):
    category_id = models.AutoField(primary_key=True)
    category_name = models.CharField(max_length=50)
    category_icon = models.CharField(max_length=500, null=True, blank=True)
    category_image = models.CharField(max_length=500, null=True, blank=True)
    category_description = models.CharField(max_length=1000, null=True, blank=True)
    active_status = models.BooleanField(default=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)
    
    
# SERIALIZER.PY
class CategoryServiceListSerializer(serializers.ModelSerializer):
    variant = VariantServiceSerializer(many=True, source="variant_set")
    class Meta:
        fields = "__all__"
        model = Category

class VariantServiceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Variant
        fields = "__all__"

output:

"data": {
            "category_id": 1,
            "category_name": "Home Cleaning",
            "variant": [
                {
                    "variant_id": 1,
                    "variant_name":
                 },
{
                    "variant_id": 2,
                    "variant_name":
                 },
{
                    "variant_id": 3,
                    "variant_name":
                 },
{
                    "variant_id": 2,
                    "variant_name":
                 }
                 ]
}

Expected_output:

req:

{"variant_id:1}

responce:

{
                "category_id": 1,
                "category_name": "Home Cleaning",
                "variant": {
                        "variant_id": 1,
                        "variant_name":
                     }
                     
1 Answers

One thing you can do is to make variant a SerializerMethodField then filter against parameters passed in the context.

In your view:

def retrieve(self, request, pk=None):
    variant_id = request.get('variant_id')
    queryset = Category.objects.filter(category_id=pk)
    querysetSerializer = CategoryServiceListSerializer(queryset, many=True, context={'variant_id': variant_id})
    [...]

In your serializer:

class CategoryServiceListSerializer(serializers.ModelSerializer):
    variant = SerializerMethodField()

    def get_variant(self, instance):
        variant_id = self.context.get('variant_id')
        if variant_id:
            variants = instance.variant_set.filter(variant_id=variant_id)
        else:
            variants = instance.variant_set.all()
        return VariantServiceSerializer(variants, many=True).data

    class Meta:
        fields = "__all__"
        model = Category
Related