Home > database >  In DRF how do I serialize a related model(OneToOne) and display the data not in a list data type but
In DRF how do I serialize a related model(OneToOne) and display the data not in a list data type but

Time:04-13

The code is given below with the present output and expected output. Please help if, Thank you. In the ProductPriceMapping table the ProductDetail table and PriceList is related with a OneToOne relation, but When the data for Price is fetched with related_name= argument there must be one value for one product, but the data is being displayed is List data type.

##models.py


class PriceList(models.Model):
    priceCode = models.BigAutoField(primary_key= True)
    maxRetailPrice= models.FloatField(max_length=20)
    baseDiscount = models.FloatField(max_length=20, default=0)
    seasonalDiscount = models.FloatField(max_length=20, default=0)

    def __str__(self):
        return '%s'% (self.maxRetailPrice)

class ProductDetail(models.Model):
    productCode = models.BigAutoField(primary_key=True)
    productName = models.CharField(max_length=100)
    manufacturer = models.CharField(max_length=100)

    def __str__(self):
        return self.productName

class ProductPriceMapping(models.Model):
    productPriceCode= models.BigAutoField(primary_key=True)
    productCode= models.ForeignKey(ProductDetail,on_delete=models.CASCADE,related_name='price')
    priceCode= models.OneToOneField(PriceList,on_delete=models.CASCADE)

    def __str__(self):
        return '%s' % (self.priceCode)

##serializers.py

from .models import CategoryDetail, EmployeeDetail, ProductCategoryMapping, ProductPriceMapping, SalaryDetail, ProductDetail, PriceList

class ProductPriceListSerializer(serializers.ModelSerializer):
    class Meta:
        model = PriceList
        fields = ('priceCode','maxRetailPrice',
                  'baseDiscount', 'seasonalDiscount')

class ProductPriceMappingSerializer(serializers.ModelSerializer):
    class Meta:
        model= ProductPriceMapping
        fields= ('productPriceCode','productCode', 'priceCode')

class ProductDetailsSerializer(serializers.ModelSerializer):
    category= serializers.StringRelatedField(many= True, read_only= True)
    price = serializers.StringRelatedField( many= True, read_only= True)
    class Meta:
        model = ProductDetail
        fields = ('productCode', 'productName', 'manufacturer','category', 'price')



The API as it looks:


[
    {
        "productCode": 1,
        "productName": "NeoChef",
        "manufacturer": "LG",
        "category": [
            "1: Microwave Oven"
        ],
        "price": [
            "26000.0"  ##expected the price value not be in a list
        ]
    },
    {
        "productCode": 2,
        "productName": "The Frame",
        "manufacturer": "Samsung",
        "category": [
            "2: Television"
        ],
        "price": [
            "120000.0" ##expected the price value not be in a list
        ]
    },
    {
        "productCode": 3,
        "productName": "Galaxy S22 ",
        "manufacturer": "Samsung",
        "category": [
            "3: Smart Phone"
        ],
        "price": [
            "79000.0" ##expected the price value not be in a list
        ]
    }
]

#expected

[
    {
        "productCode": 1,
        "productName": "NeoChef",
        "manufacturer": "LG",
        "category": [
            "1: Microwave Oven"
        ],
        "price": "26000.0"  
    }
]```

CodePudding user response:

In your case, the price field is not a one-to-one related field, you either need to change the productCode to OneToOneField or if you don't want to change the DB field, you can achieve the same result simply with SerializerMethodField. In the first case, removing many=True argument from the serializer field should help. In second case, SerializerMethodField will help you to make your custom representation, e.g.:

class ProductDetailsSerializer(serializers.ModelSerializer):
    category= serializers.StringRelatedField(many=True, read_only=True)
    price = serializers.SerializerMethodField()

    class Meta:
        model = ProductDetail
        fields = ('productCode', 'productName', 'manufacturer','category', 'price')

    def get_price(self, obj):
        # If it's guaranteed that there will be only one related object, or retrieve the needed object depending on your demands
        return str(obj.price.first())

CodePudding user response:

One simple way is to use MethodField...

class ProductPriceMappingSerializer(serializers.ModelSerializer):
    priceCode = serializers.SerializerMethodField()

    class Meta:
        model= ProductPriceMapping
        fields= ('productPriceCode','productCode', 'priceCode')
    
    @staticmethod
    def get_priceCode(obj):
        return obj.priceCode.maxRetailPrice  # or any other fields that you like to show in your response

but if you want to show all of the priceList fields based on your other serializer you can do something like:

class ProductPriceMappingSerializer(serializers.ModelSerializer):
    priceCode = ProductPriceListSerializer()

    class Meta:
        model= ProductPriceMapping
        fields= ('productPriceCode','productCode', 'priceCode')

CodePudding user response:

Thank you guys, solved

##models.py

class ProductPriceMapping(models.Model):
    productPriceCode= models.BigAutoField(primary_key=True)
    productCode= models.OneToOneField(ProductDetail,on_delete=models.CASCADE,related_name='price')
    priceCode= models.ForeignKey(PriceList,on_delete=models.CASCADE)

    def __str__(self):
        return '%s' % (self.priceCode)

#serializers.py

class ProductDetailsSerializer(serializers.ModelSerializer):
    category= serializers.StringRelatedField(many= True, read_only= True)
    price = serializers.StringRelatedField(read_only= True)
    class Meta:
        model = ProductDetail
        fields = ('productCode', 'productName', 'manufacturer','category', 'price')
  • Related