P5291
P5291

Reputation: 51

Filter on nested serializer and Foreing Key Django/Rest Framework

Following are my model classes

class ProductClass(models.Model):
    name = models.CharField('Name')

class Product(models.Model):
    title = models.CharField('Product title')
    description = models.TextField('Description')
    product_class = models.ForeignKey(ProductClass, null=True, blank=True, related_name='products')

class ProductPriceRepository(models.Model):
    product = models.ForeignKey(Product, related_name='price_repo')

    price = models.DecimalField('price of product', max_digits=7, decimal_places=2)

    location = models.ForeignKey(Location,blank=True, null=True, related_name='price_repo')

    is_default = models.BooleanField()

This is how I have defined my view

class ProductClassList(APIView):
    def get(self, request, format=None):
        product_classes = ProductClass.objects.filter(products__price_repo__is_default=True)
        serializer = ProductClassSerializer(product_classes, many=True)
        return Response(serializer.data)

I have defined serializes as follow

class ProductPriceRepositorySerializer(serializers.ModelSerializer):
    class Meta:
        model = ProductPriceRepository
        fields = ('price',)


class ProductSerializer(serializers.ModelSerializer):
    price = SerializerMethodField()

    class Meta:
        model = Product
        fields = ('title', 'description', 'price')

    def get_price(self, obj):
        for price in obj.price_repo.all():
            if price.is_default:
                serializer = ProductPriceRepositorySerializer(price)
                return serializer.data


class ProductClassSerializer(serializers.ModelSerializer):
    products = SerializerMethodField()

    class Meta:
        model = ProductClass
        fields = ('name', 'products')

    def get_products(self, obj):
        for product in obj.products.all():
            for price in product.price_repo.all():
                if price.is_default:
                    serializer = ProductSerializer(product)
                    return serializer.data

Output looks like

[ { "name": "Product Class Test One", "products": { "title": "Test Product One", "description": "", "price": { "price": "100.00" } } }, { "name": "Product Class Test Two", "products": { "title": "Test Product Two", "description": "", "price": { "price": "30.00" } } } ]

I am using SerializerMethodField to filter out default prices for a given product class Is there more efferent way to achieve the same?

Upvotes: 0

Views: 134

Answers (1)

JPG
JPG

Reputation: 88429

Try something like this,

class ProductClassSerializer(serializers.ModelSerializer):
    products = serializers.SerializerMethodField()

    class Meta:
        model = ProductClass
        fields = ('name', 'products')

    def get_products(self, obj):
        return ProductSerializer(ProductPriceRepository.objects.filter(is_default=True, product__product_class=obj),
                                 many=True).data

Upvotes: 1

Related Questions