How can group this relations on Django Rest Framework

Currently, I've the next models:


class Product(models.Model):
    name = models.CharField('name', max_length=60)


class Variant(models.Model):
    name = models.CharField('name', max_length=60)


class VariantValue(models.Model):
    value = models.CharField('value', max_length=60)
    variant = models.ForeigKey('variant', to=Variant, on_delete=models.CASCADE)    
    product = models.ForeigKey('product', to=Product, on_delete=models.CASCADE)    

I want to get the next json result:

{
    "name": "My product",
    "variants": [
        {
            "variant_id": 1,
            "values": ["Value 1", "Value 2", "Value 3"]
        },
        {
            "variant_id": 2,
            "values": ["Value 4", "Value 5", "Value 6"]
        },
    ]
}

It's possible with a Serializer or do I've to make the json manually?

I only have the next ModelSerializer:

class ProductModelSerializer(serializers.ModelSerializer):
    variant_list = serializers.SerializerMethodField('get_variant_list', read_only=True)

    class Meta:
         model = Product
         fields = [..., 'variant_list']

    def get_variant_list(self, obj):
        variant_list = VariantValue.objects.filter(product_id=obj.id)
        variant_list_grouped = variant_list.values('variant', 'value').annotate(count=Count('variant'))
        res = []
        for variant in variant_list_grouped:
            pass
        return []

Thanks!

Upvotes: 1

Views: 57

Answers (3)

jeevu94
jeevu94

Reputation: 718

Create a new serializer for VariantValue and nest it thats it. eg:

# serializer
class VariantValueSerializer(serializers.ModelSerializer):
    variant_id = serializer.IntegerField(source="id", read_only=True)
    
    class Meta:
        model = VariantValue
        fields = ["variant_id", "values"]

class ProductModelSerializer(serializers.ModelSerializer):
    variant_list = VariantValueSerializer(source="variantvalue_set", many=True, read_only=True)
   
    class Meta:
         model = Product
         fields = [..., 'variant_list']

you dont have to manually format serializers are there for it.

Upvotes: 0

Using Krishna Singhal answer as a basis I achieved the following script

def get_variant_list(self, product):
    variant_list = VariantValue.objects.filter(product_id=obj.id)
    variant_list_grouped = variant_list.values('variant',).annotate(count=Count('variant'))

    return [{"variant": variant['variant'], "values": VariantValue.objects.filter(
                product_id=obj.id, variant_id=variant['variant']).distinct('value').values_list('value', flat=True)} for variant in variant_list_grouped]

I get the next json:

{
    ...,
    "variantList": [
        {
            "variant": 1,
            "values": [
                "Value 1",
                "Value 2"
            ]
        },
        {
            "variant": 3,
            "values": [
                "Black",
                "Red",
                "Green"
            ]
        },
        {
            "variant": 2,
            "values": [
                "S",
                "M",
                "G"
            ]
        }
    ],
}

Upvotes: 0

Krishna Singhal
Krishna Singhal

Reputation: 661

class ProductModelSerializer(serializers.ModelSerializer):
    variant_list = serializers.SerializerMethodField('get_variant_list', read_only=True)

    class Meta:
         model = Product
         fields = [..., 'variant_list']

    def get_variant_list(self, obj):
        variant_list = VariantValue.objects.filter(product_id=obj.id)
        return [{"variant_id": variant.variant_id, "values": VariantValue.objects.filter(variant_id = variant.variant_id).values("values", flat=True)} for variant in variant_list]

Upvotes: 1

Related Questions